gpt4 book ai didi

wpf - 从 Catel WPF UserControl 中的 ResourceDictionary 中绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 10:17:37 26 4
gpt4 key购买 nike

作为概念验证,我正在将我们的 WPF 应用程序的一些 View 和 View 模型转换为 Catel。

其中一个用户控件似乎在运行时没有正确绑定(bind)到 View 模型。我想我明白为什么会这样,但想得到一些关于什么是最好的补救措施的反馈。

编码

我有一个简单的 View ,其模型实际上是 ObservableCollection :
PersonTable.xaml
需要注意的关键事项:我使用的是 CollectionViewSource包装了 DataGrid 的主要集合绑定(bind)到。这样我就可以保持网格自动排序。

<catel:UserControl x:Class="MyApp.PersonTable"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
xmlns:catel="http://catel.codeplex.com"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="200" d:DataContext="{DynamicResource DesignTimeViewModel}">
<UserControl.Resources>
<ResourceDictionary>
<CollectionViewSource Source="{Binding PersonItems}" x:Key="PersonItemsSource">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="DOB" Direction="Descending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>

<ui:DesignPersonViewModel x:Key="DesignTimeViewModel" />
</ResourceDictionary>
</UserControl.Resources>

<Grid>
<DataGrid ItemsSource="{Binding Source={StaticResource PersonItemsSource}}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name, Mode=TwoWay}"
Header="Name" Width="90"
ElementStyle="{StaticResource CellRightAlign}" />
<!-- etc..... -->
</DataGrid.Columns>
</DataGrid>
</Grid>
</catel:UserControl>
PersonTableViewModel.cs
View 模型在构造函数中接受模型:
using Catel.MVVM;

public class PersonTableViewModel : ViewModelBase
{
public PersonTableViewModel(ObservableCollection<Person> personItems)
{
this.PersonItems = personItems
}

public ObservableCollection<Person> PersonItems
{
get { return GetValue<ObservableCollection<Person>>(PersonItemsProperty); }
set { SetValue(PersonItemsProperty, value); }
}

public static PropertyData PersonItemsProperty =
RegisterProperty("PersonItems", typeof(ObservableCollection<Person>), () => new ObservableCollection<PersonItems>());
}

问题

在运行时,网格中不会填充任何项目。尽管在设计时,设计 View 模型确实正确地填充了设计 View 中的网格。

我对问题的根源是否正确? 我相信这是绑定(bind)到 PersonItems 的控件。属性不是可视化树的一部分,而是嵌入在控件级资源字典中?根据我对文档的阅读,特别是文章 UserControl - Under the hood , 看来Catel UserControl类将 View 模型注入(inject)为隐藏的内部 DataContext仅在可视化树内,但我的 {Binding}在资源字典项目中可能会被冷落。

假设我是对的,最好的补救措施是什么?

如果我对上述内容是正确的,那么我可以想到一些可能的补救措施,但没有一个看起来是完美的。我很想知道什么是公认的最佳实践来纠正这种情况。
  • 移动CollectionViewSource到后面的代码;将其公开为依赖属性。我不喜欢这个选项,因为我不能在 XAML 中配置它。
  • 移动CollectionViewSource到 View 模型。我真的不喜欢这个;将 WPF 组件放在 View 模型中会破坏 MVVM。
  • 绑定(bind)CollectionViewSource转至原文DataContext (即模型)。那里的问题是设计时 View 模型将无法正确绑定(bind)。
    <CollectionViewSource Source="{Binding}" ..... >
  • 从绑定(bind)到 View 模型的代码隐藏中公开依赖属性。更新:这在运行时有效,但现在在设计时失败(因为网格不包含测试数据。)
    ---- PersonTable.xaml.cs ----

    [ViewToViewModel(MappingType = ViewToViewModelMappingType.ViewModelToView]
    public ObservableCollection<PersonItem> PersonItems { get { ... } }

    ---- PersonTable.xaml ----

    <CollectionViewSource Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PersonTable}}, Path=PersonItems}" ...... >
  • 最佳答案

    你的假设都是正确的。但是还有第四个补救措施。将 Resources 放入 Grid 中,以便您位于 ViewModel 数据上下文中:

    <catel:UserControl x:Class="MyApp.PersonTable"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
    xmlns:catel="http://catel.codeplex.com"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="200" d:DataContext="{DynamicResource DesignTimeViewModel}">

    <Grid>
    <Grid.Resources>
    <ResourceDictionary>
    <CollectionViewSource Source="{Binding PersonItems}" x:Key="PersonItemsSource">
    <CollectionViewSource.SortDescriptions>
    <scm:SortDescription PropertyName="DOB" Direction="Descending" />
    </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>

    <ui:DesignPersonViewModel x:Key="DesignTimeViewModel" />
    </ResourceDictionary>
    </Grid.Resources>

    <DataGrid ItemsSource="{Binding Source={StaticResource PersonItemsSource}}" AutoGenerateColumns="False">
    <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Name, Mode=TwoWay}"
    Header="Name" Width="90"
    ElementStyle="{StaticResource CellRightAlign}" />
    <!-- etc..... -->
    </DataGrid.Columns>
    </DataGrid>
    </Grid>
    </catel:UserControl>

    关于wpf - 从 Catel WPF UserControl 中的 ResourceDictionary 中绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31488173/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com