【问题标题】:Get Element Root's ViewModel Context in WINUI3WINUI3中获取Element Root\'s ViewModel Context
【发布时间】:2022-10-15 06:10:16
【问题描述】:

我有一个页面,其中包含一个 ListView x:绑定到我的 ViewModel 中的一个对象。此对象包含一个对象列表(时间戳),其中包含一个主题列表,其中包含另一个对象的列表。我在 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 持有的对象(主题)中包含的数据。 我可以尝试将数据模板上下文设置为 ViewModel,但它会破坏主题绑定。

我发现了很多关于这个主题的问题,但与 WPF 不同的是,没有 AncestorType 来获取向上的树引用。

观察: 我的项目基于模板模型,它使用 ViewModel 作为属性创建 XAML .cs​​。我也没有在 XAML 页面上设置 DataContext,因为我可以 x:bind 通常将我的视图模型绑定到页面元素而无需显式设置。

有没有办法在不使用附加属性的情况下完成? 谢谢你。

【问题讨论】:

  • “不使用附加属性”作为仅 XAML 的解决方案?不。
  • 所以到目前为止还没有替代 AncestorType?

标签: xaml mvvm winui-3 winui


【解决方案1】:

由于不支持在 WinUI 中设置 RelativeSourceAncestorType 属性,因此如果不编写一些代码,就无法在纯 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);
    }
}

所以到目前为止还没有替代 AncestorType?

不,不在 XAML 中。

【讨论】:

  • 希望将来能实现 xaml。谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-01-07
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 2021-08-08
  • 2023-01-18
  • 2021-10-23
  • 2021-12-06
相关资源
最近更新 更多