WINUI3获取Element Root的ViewModel Context
Get Element Root's ViewModel Context in WINUI3
我有一个页面,其中包含指向我的 ViewModel 中的对象的 ListView x:bound。该对象包含对象列表(时间戳),对象列表包含主题列表,主题列表包含其他对象列表。我在 2 个列表视图中显示数据,一个在另一个列表视图中。
<ListView
x:Name="primaryList" // for exemplification purposes
ItemsSource="{x:Bind ViewModel.VideoProject.TimeStamps, Mode=OneWay}"
ItemClick='{x:Bind ViewModel.ListViewTimeStamps_ItemClick, Mode=OneWay}'>
ListView 包含另一个 ListView 的 DataTemplate
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Spacing="5">
<TextBlock Text="{Binding Id}"
FontSize="15"
HorizontalAlignment="Left"
FontWeight="Bold" />
<ListView ItemsSource="{Binding Subjects}"
x:Name="secondaryList"
SelectionMode="Multiple">
<ListView.ItemTemplate>
....
而第二个ListView后面是另一个相同的结构。
我的目标是将第二个 ListView ItemClickEvent 绑定到我的 ViewModel 中的 ListViewTimeStamps_ItemClick 方法,因为我需要包含在 secondaryListView 持有的对象 (Subject) 中的数据。
我可以尝试将数据模板上下文设置为 ViewModel,但它会破坏主题绑定。
我发现了很多关于这个主题的问题,但与 WPF 不同的是,没有 AncestorType 来赶上树参考。
观察:
我的项目基于模板模型,它创建 XAML .cs 并将 ViewModel 作为 属性。我也没有在 XAML 页面上设置 DataContext,因为我可以 x:bind 通常将我的视图模型设置为没有显式设置的页面元素。
有没有不用附加属性就可以完成的方法?
谢谢。
由于在 WinUI 中不支持设置 RelativeSource
的 AncestorType
属性,因此如果不编写一些代码,就无法在纯 XAML 中完成此操作代码。
您可以按照建议和示例实施附加行为 here:
public static class AncestorSource
{
public static readonly DependencyProperty AncestorTypeProperty =
DependencyProperty.RegisterAttached(
"AncestorType",
typeof(Type),
typeof(AncestorSource),
new PropertyMetadata(default(Type), OnAncestorTypeChanged)
);
public static void SetAncestorType(FrameworkElement element, Type value) =>
element.SetValue(AncestorTypeProperty, value);
public static Type GetAncestorType(FrameworkElement element) =>
(Type)element.GetValue(AncestorTypeProperty);
private static void OnAncestorTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement target = (FrameworkElement)d;
if (target.IsLoaded)
SetDataContext(target);
else
target.Loaded += OnTargetLoaded;
}
private static void OnTargetLoaded(object sender, RoutedEventArgs e)
{
FrameworkElement target = (FrameworkElement)sender;
target.Loaded -= OnTargetLoaded;
SetDataContext(target);
}
private static void SetDataContext(FrameworkElement target)
{
Type ancestorType = GetAncestorType(target);
if (ancestorType != null)
target.DataContext = FindParent(target, ancestorType);
}
private static object FindParent(DependencyObject dependencyObject, Type ancestorType)
{
DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null)
return null;
if (ancestorType.IsAssignableFrom(parent.GetType()))
return parent;
return FindParent(parent, ancestorType);
}
}
So no replacement so far for AncestorType?
没有。不在 XAML.
我有一个页面,其中包含指向我的 ViewModel 中的对象的 ListView x:bound。该对象包含对象列表(时间戳),对象列表包含主题列表,主题列表包含其他对象列表。我在 2 个列表视图中显示数据,一个在另一个列表视图中。
<ListView
x:Name="primaryList" // for exemplification purposes
ItemsSource="{x:Bind ViewModel.VideoProject.TimeStamps, Mode=OneWay}"
ItemClick='{x:Bind ViewModel.ListViewTimeStamps_ItemClick, Mode=OneWay}'>
ListView 包含另一个 ListView 的 DataTemplate
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Spacing="5">
<TextBlock Text="{Binding Id}"
FontSize="15"
HorizontalAlignment="Left"
FontWeight="Bold" />
<ListView ItemsSource="{Binding Subjects}"
x:Name="secondaryList"
SelectionMode="Multiple">
<ListView.ItemTemplate>
....
而第二个ListView后面是另一个相同的结构。
我的目标是将第二个 ListView ItemClickEvent 绑定到我的 ViewModel 中的 ListViewTimeStamps_ItemClick 方法,因为我需要包含在 secondaryListView 持有的对象 (Subject) 中的数据。 我可以尝试将数据模板上下文设置为 ViewModel,但它会破坏主题绑定。
我发现了很多关于这个主题的问题,但与 WPF 不同的是,没有 AncestorType 来赶上树参考。
观察: 我的项目基于模板模型,它创建 XAML .cs 并将 ViewModel 作为 属性。我也没有在 XAML 页面上设置 DataContext,因为我可以 x:bind 通常将我的视图模型设置为没有显式设置的页面元素。
有没有不用附加属性就可以完成的方法? 谢谢。
由于在 WinUI 中不支持设置 RelativeSource
的 AncestorType
属性,因此如果不编写一些代码,就无法在纯 XAML 中完成此操作代码。
您可以按照建议和示例实施附加行为 here:
public static class AncestorSource
{
public static readonly DependencyProperty AncestorTypeProperty =
DependencyProperty.RegisterAttached(
"AncestorType",
typeof(Type),
typeof(AncestorSource),
new PropertyMetadata(default(Type), OnAncestorTypeChanged)
);
public static void SetAncestorType(FrameworkElement element, Type value) =>
element.SetValue(AncestorTypeProperty, value);
public static Type GetAncestorType(FrameworkElement element) =>
(Type)element.GetValue(AncestorTypeProperty);
private static void OnAncestorTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement target = (FrameworkElement)d;
if (target.IsLoaded)
SetDataContext(target);
else
target.Loaded += OnTargetLoaded;
}
private static void OnTargetLoaded(object sender, RoutedEventArgs e)
{
FrameworkElement target = (FrameworkElement)sender;
target.Loaded -= OnTargetLoaded;
SetDataContext(target);
}
private static void SetDataContext(FrameworkElement target)
{
Type ancestorType = GetAncestorType(target);
if (ancestorType != null)
target.DataContext = FindParent(target, ancestorType);
}
private static object FindParent(DependencyObject dependencyObject, Type ancestorType)
{
DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null)
return null;
if (ancestorType.IsAssignableFrom(parent.GetType()))
return parent;
return FindParent(parent, ancestorType);
}
}
So no replacement so far for AncestorType?
没有。不在 XAML.