XAML中的Source和DataContext有什么区别?

4
这些方法中哪个最好?
<Window.Resources>
    <sys:Int16 x:Key="MyValue">123</sys:Int16>
</Window.Resources>

<StackPanel>

    <!-- method 1 -->
    <TextBlock Text="{Binding}" DataContext="{StaticResource MyValue}" />

    <!-- method 2 -->
    <TextBlock Text="{Binding, Source={StaticResource MyValue}}" />

</StackPanel>
3个回答

5

像许多“哪个更好”的问题一样,我会说“这取决于”上下文。

它们都存在是因为它们在不同的情境下都可以发挥作用。根据你上面展示的内容,我会选择示例2。

然而,当你设置DataContext时,它的所有子项都将继承该DataContext。所以也许你正在使用一个Button。在你的Button中,你想要把它变得更加华丽,并每次显示四次文本,每次使用不同的颜色。如下所示,此时我会选择示例1。

示例1:(请注意,DataContext在按钮上,而TextBlocks不需要像示例2中那样使用Source)

<Button DataContext="{StaticResource MyValue}" Height="Auto" Width="Auto" HorizontalAlignment="Center" VerticalAlignment="Center">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding}" Foreground="Red" />
        <TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding}" Foreground="Blue" />
        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding}" Foreground="Yellow"/>
        <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding}" Foreground="Green" />
    </Grid>
</Button>

示例2:

<Button Height="Auto" Width="Auto" HorizontalAlignment="Center" VerticalAlignment="Center">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding, Source={StaticResource MyValue}}" Foreground="Red" />
        <TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding, Source={StaticResource MyValue}}" Foreground="Blue" />
        <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding, Source={StaticResource MyValue}}" Foreground="Yellow"/>
        <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding, Source={StaticResource MyValue}}" Foreground="Green" />
    </Grid>
</Button>

当您绑定到一个简单对象,如您的情况下的Int16时,您可能只会绑定和显示该值一次,因此选项2最为合适。

一个好的经验法则...如果您发现自己将“源”设置为多个绑定的相同内容,则应该只将通用父FrameworkElement的DataContext进行绑定。


1

DataContenxt DependencyProperty允许您轻松地跨DependencyObject的所有属性进行绑定。

Binding的Source DependenceyProperty允许您将特定绑定指向所需的源,而不考虑DataContext。

当您为ListView执行更复杂的绑定时,这变得非常有用。例如:

<Window.Resources>
  <local:MyConverter x:Key="MyConverter" />
</Window.Resources>
<Grid>
  <ComboBox ItemsSource="{Binding Source={StaticResource MyConverter}, Path=DisplayValues}" DataContenxt={Binding ElementName=lvwItems Path=SelectedItem} SelectedItem="{Binding Converter={StaticResource MyConverter}"/>
<ListView Name="lvwItems"......

上面的例子展示了我将itemssource设置为'MyConverter'中名为DisplayValues的属性,但是我正在处理的是combobox的数据上下文,它正在处理名为'lvwItems'的ListView的SelectedItem属性。
希望这可以帮到你。

1
但我的问题是关于哪种方法最好。 - Jerry Nixon
1
根据您需要处理其他绑定的方式,两种方法都可以是最佳选择。如果您需要在对象上进行更多的绑定,则绑定到DataContext是最佳方法。如果只是针对该属性的简单绑定,则指定源是最佳方法。 - Andrew Riebe

1

如果我必须在两者之间进行选择,我会选择方法2。DataContext实际上更适用于将项目数据绑定到更复杂的底层对象,并简化多个数据值的数据绑定。

只是出于好奇,你为什么要这样做?你的代码是否在某个时刻更改了MyValue的值?有没有更好的方式可以让你以某种原因这样做?


我只是试图提出一个简单的例子来问这个问题;我从未实际绑定过像这样(使用单个值)的数据,但我想知道DataContext和Source之间是否有一个好的方法。感谢您的贡献。 - Jerry Nixon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接