如何识别.xaml中不同项的DataContext?
How to identify the DataContext of different items in .xaml?
我有一个 FilterUserControl,FilterViewModel 作为它的 DataContext。
在 FilterControl.xaml:
<Button x:Name="FilterButton">
<Button.ContextMenu PlacementTarget="{x:Reference FilterButton}" ItemsSource="{Binding FilterConditions}" Style="{StaticResource ButtonContextMenu}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<MenuItem Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}, Path=DataContext.ChangeFilterCondition}"
CommandParameter="{Binding}">
...
网上查了一下才知道
CommandParameter="{Binding}"
与
相同
CommandParameter="{Binding DataContext,RelativeSource={RelativeSource Self}}"
我本来以为DataContext会是FilterViewModel但是调试后发现DataContext其实是“FilterConditions的每一项”
终于拿到证据了ItemsSource vs DataContext in binding case
现在我想知道在 .xaml 我们如何识别 DataContext 是什么? typical/common 个案例是什么?谢谢。
itemscontrol(或继承自 itemscontrol 的事物)只有一种情况。
https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.itemscontrol?view=netcore-3.1
当您将 itemssource 绑定到集合时。
该集合中的每个项目都会出现。
Datatemplating 然后给出您在模板中指定的任何 UI 的实例。
该行 UI 出现在您的项目控制项目面板中。
行 UI 具有项目的数据上下文。
您可以使用数据模板选择器或与数据类型关联的数据模板,以便获得不同的 UI。
您可以更改显示这些的项目面板,例如 canvas 而不是默认的堆栈面板。
但是无论您做什么,每个的数据上下文都将是您绑定到 itemssource 的集合中的那些项目之一。
长话短说:在分配了 ItemsSource
的 ItemsControl
中,您可以确定 每个项目 有一个不同的 DataContext
,这意味着 ItemTemplate
和 ItemContainerStyle
。不是 ItemsPanel
.
DataContext
是绑定路径的根,它在整个 XAML 层次结构中保持不变,除非您更改它。
您可以明确更改 DataContext
或通过更改 ItemsSource
。 具有 ItemsSource
会更改每个元素的 DataContext
,因此您不必处理索引。
当您分配给 Items
时,这不是真的,因为它隐式地将它们添加到 ItemCollection
并清除 ItemsSource
。使用 Items
类似于将项目添加到任何其他控件。即本例中 DataContext
的内容:
<ItemsControl>
<Button Content="{Binding A}"/>
</ItemsControl>
就像这个案例:
<StackPanel>
<Button Content="{Binding A}"/>
</StackPanel>
甚至:
<Button>
<Button Content="{Binding A}"/>
</Button>
但是使用 ItemsSource
意味着您要求 ItemsControl
枚举给定的集合,获取每个元素,设置它们的 DataContext
并呈现它们。因此 DataContext
在那里被改变了。
RelativeSource Self
解析为当前的 XAML 元素,所以这两个是相等的:
<... Prop="{Binding Path=Width, RelativeSource={RelativeSource Self}}"/>
<... Prop="{Binding Path=Width, ElementName=name}" x:Name="name"/>
DataContext
始终是绑定的根对象({Binding}
或 {Binding Path=.}
),所以这三个是相等的:
<... Prop="{Binding Path=A}"/>
<... Prop="{Binding Path=DataContext.A, RelativeSource={RelativeSource Self}}"/>
<... Prop="{Binding Path=DataContext.A, ElementName=name}" x:Name="name"/>
对象树中所有对象的默认绑定路径总是解析为同一个对象(除非它们被更改)。例如如果 grid.DataContext=A
则 A
是分层网格对象树中所有对象的绑定根。
请注意,您可以在代码中更改 DataContext(最好在视图的构造函数中),或者您可以“绑定”DataContext
以具有不同的范围,以便此视图:
<Grid DataContext="{Binding}"> // this is redundant and points to VM
<Grid DataContext="{Binding Child1}">
<Button Command="{Binding Action11}"/>
<Button Command="{Binding Action12}"/>
</Grid>
<Grid DataContext="{Binding Child2}">
<Button Command="{Binding Action21}"/>
<Button Command="{Binding Action22}"/>
</Grid>
<ItemsControl ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
DataContext="{Binding}" // this is redundant and points to an item
Command="{Binding ElementAction}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
完美代表此虚拟机:
VM
Child1
Action11
Action12
Child2
Action21
Action22
Collection
Item1
ElementAction
Item2
ElementAction
Item3
ElementAction
...
我有一个 FilterUserControl,FilterViewModel 作为它的 DataContext。 在 FilterControl.xaml:
<Button x:Name="FilterButton">
<Button.ContextMenu PlacementTarget="{x:Reference FilterButton}" ItemsSource="{Binding FilterConditions}" Style="{StaticResource ButtonContextMenu}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<MenuItem Command="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu, Mode=FindAncestor}, Path=DataContext.ChangeFilterCondition}"
CommandParameter="{Binding}">
...
网上查了一下才知道
CommandParameter="{Binding}"
与
相同CommandParameter="{Binding DataContext,RelativeSource={RelativeSource Self}}"
我本来以为DataContext会是FilterViewModel但是调试后发现DataContext其实是“FilterConditions的每一项”
终于拿到证据了ItemsSource vs DataContext in binding case
现在我想知道在 .xaml 我们如何识别 DataContext 是什么? typical/common 个案例是什么?谢谢。
itemscontrol(或继承自 itemscontrol 的事物)只有一种情况。
https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.itemscontrol?view=netcore-3.1
当您将 itemssource 绑定到集合时。
该集合中的每个项目都会出现。 Datatemplating 然后给出您在模板中指定的任何 UI 的实例。
该行 UI 出现在您的项目控制项目面板中。
行 UI 具有项目的数据上下文。
您可以使用数据模板选择器或与数据类型关联的数据模板,以便获得不同的 UI。
您可以更改显示这些的项目面板,例如 canvas 而不是默认的堆栈面板。
但是无论您做什么,每个的数据上下文都将是您绑定到 itemssource 的集合中的那些项目之一。
长话短说:在分配了 ItemsSource
的 ItemsControl
中,您可以确定 每个项目 有一个不同的 DataContext
,这意味着 ItemTemplate
和 ItemContainerStyle
。不是 ItemsPanel
.
DataContext
是绑定路径的根,它在整个 XAML 层次结构中保持不变,除非您更改它。
您可以明确更改 DataContext
或通过更改 ItemsSource
。 具有 ItemsSource
会更改每个元素的 DataContext
,因此您不必处理索引。
当您分配给 Items
时,这不是真的,因为它隐式地将它们添加到 ItemCollection
并清除 ItemsSource
。使用 Items
类似于将项目添加到任何其他控件。即本例中 DataContext
的内容:
<ItemsControl>
<Button Content="{Binding A}"/>
</ItemsControl>
就像这个案例:
<StackPanel>
<Button Content="{Binding A}"/>
</StackPanel>
甚至:
<Button>
<Button Content="{Binding A}"/>
</Button>
但是使用 ItemsSource
意味着您要求 ItemsControl
枚举给定的集合,获取每个元素,设置它们的 DataContext
并呈现它们。因此 DataContext
在那里被改变了。
RelativeSource Self
解析为当前的 XAML 元素,所以这两个是相等的:
<... Prop="{Binding Path=Width, RelativeSource={RelativeSource Self}}"/>
<... Prop="{Binding Path=Width, ElementName=name}" x:Name="name"/>
DataContext
始终是绑定的根对象({Binding}
或 {Binding Path=.}
),所以这三个是相等的:
<... Prop="{Binding Path=A}"/>
<... Prop="{Binding Path=DataContext.A, RelativeSource={RelativeSource Self}}"/>
<... Prop="{Binding Path=DataContext.A, ElementName=name}" x:Name="name"/>
对象树中所有对象的默认绑定路径总是解析为同一个对象(除非它们被更改)。例如如果 grid.DataContext=A
则 A
是分层网格对象树中所有对象的绑定根。
请注意,您可以在代码中更改 DataContext(最好在视图的构造函数中),或者您可以“绑定”DataContext
以具有不同的范围,以便此视图:
<Grid DataContext="{Binding}"> // this is redundant and points to VM
<Grid DataContext="{Binding Child1}">
<Button Command="{Binding Action11}"/>
<Button Command="{Binding Action12}"/>
</Grid>
<Grid DataContext="{Binding Child2}">
<Button Command="{Binding Action21}"/>
<Button Command="{Binding Action22}"/>
</Grid>
<ItemsControl ItemsSource="{Binding Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
DataContext="{Binding}" // this is redundant and points to an item
Command="{Binding ElementAction}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
完美代表此虚拟机:
VM
Child1
Action11
Action12
Child2
Action21
Action22
Collection
Item1
ElementAction
Item2
ElementAction
Item3
ElementAction
...