gpt4 book ai didi

c# - 如何将 Linq 结果绑定(bind)到 WPF DataGrid,同时保持两种方式绑定(bind) MVVM

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

所以我非常了解我的问题,我只是在为它开发解决方案时遇到问题。假设我有一个带有数据网格的 MVVM WPF 应用程序。 ItemSource 绑定(bind)到集合 ObservableCollection。这是通过转换器馈送的,因为数据模型相当复杂,但模型复杂性与问题没有任何关系。然后我需要对我的可观察集合使用 Linq 查询,因为我希望它只显示该集合中的某些项目。

如果我直接从我的转换器返回 Linq 查询,我会收到错误“'EditItem' is not allowed for this view”。我意识到发生该错误是因为 Linq 查询返回一个 IEnumerable 集合,DataGrid TwoWay 数据绑定(bind)不支持该集合。

但是,如果我将它作为新的 ObservableCollection 返回,我会收到错误消息“双向绑定(bind)需要 Path 或 XPath”。这是有道理的,因为新集合不是具有访问器和修改器的属性,而且,我们以这种方式失去了与原始源的数据绑定(bind)。

所以这里的问题是我如何只从转换器返回我需要的项目,以使我的数据绑定(bind)到原始源并允许双向绑定(bind)?

我不确定以下是否有必要,但可能值得注意的是有关此应用程序的背景。此应用程序在选项卡控件中动态生成了选项卡,并且每个选项卡项都包含这些 DataGrid 之一。这些数据网格填充了相同的对象集合,只是在每个对象上使用不同的过滤器,具体取决于它包含在哪个选项卡中(这都与模型相关联)。转换器的存在很重要,因为将项目添加到任何数据网格都需要一些额外的编码。

这是一些代码来演示该问题。

XAML 数据网格:

<DataGrid IsReadOnly="False">
<DataGrid.ItemsSource>
<MultiBinding Converter="{StaticResource MyObjectCollectionDataGridConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="StateManager.MyObjectCollection" Mode="TwoWay"/>
<Binding Mode="OneWay"/>
</MultiBinding>
</DataGrid.ItemsSource>
</DataGrid>

C# 转换器
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string header = ((MyObjectType)values[1]).Name;

// Returning as a Linq query:
// return ((ObservableCollection<MyObject>)values[0]).Where(c => c.Type.Name == header);

// Returning as a new Observable Collection
return new ObservableCollection<MyObject>(((ObservableCollection<MyObject>)values[0]).Where(c => c.Type.Name == header));
}

感谢您的任何帮助!!!

编辑

好的,所以我确实发现,当使用 Linq 查询方法时,通过调用 ToList() 方法,我的数据绑定(bind)确实适用于现有项目(这是有道理的,因为它只是引用对象的旧实例)。但是,当通过数据网格添加新项目时,应用程序会因错误“双向绑定(bind)需要 Path 或 XPath”而中断。 (这也是有道理的,因为它没有引用创建的新列表,而不是旧的 observable 集合)。如何做到这一点,以便我仍然可以通过数据网格添加项目以在新列表上引用旧的 observable 集合?

最佳答案

由于 View 规定了 VM 的外观,因此您的 MyObject 也应遵循此规则。

您想扩展 MyObject 类以包含项目是否可见的标志。

这就是您的 RowViewModel 的外观:

public class MyObject : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}

private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
OnPropertyChanged();
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged([CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}

以下是在转换器中处理它的方法:
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string header = ((MyObject)values[1]).Name;
foreach (var item in (ObservableCollection<MyObject>)values[0])
item.IsEnabled = item.Name == header;

return values[0];
}

当然,您希望在 DataTemplate 中公开启用标志xml:
<DataGrid IsReadOnly="False" AutoGenerateColumns="False">
<DataGrid.ItemsSource>
<MultiBinding Converter="{StaticResource MyObjectCollectionDataGridConverter}" UpdateSourceTrigger="PropertyChanged">
<Binding Path="StateManager.MyObjectCollection" Mode="TwoWay"/>
<Binding Mode="OneWay"/>
</MultiBinding>
</DataGrid.ItemsSource>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="Hello" IsEnabled="{Binding IsEnabled}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

关于c# - 如何将 Linq 结果绑定(bind)到 WPF DataGrid,同时保持两种方式绑定(bind) MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39838138/

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