如何将Linq结果绑定到WPF DataGrid,同时保持双向绑定MVVM
所以我理解我的问题相当好,我只是有问题开发解决方案。假设我有一个带有数据网格的MVVM WPF应用程序。 ItemSource绑定到一个集合ObservableCollection。由于数据模型相当复杂,这是通过转换器提供的,但模型复杂性与问题无关。然后我需要在我的可观察集合上使用Linq查询,因为我希望它只显示该集合中的某些项目。如何将Linq结果绑定到WPF DataGrid,同时保持双向绑定MVVM
如果我直接从我的转换器返回LINQ查询,我得到的错误“‘EditItem’不允许这种观点。”我意识到发生的错误,因为LINQ查询返回IEnumerable集合,这是不支持DataGrid TwoWay数据绑定。但是,如果我将它作为新的ObservableCollection返回,则会出现错误“双向绑定需要Path或XPath。”“这很有意义,因为新集合不是具有访问器和增变器的属性, ,我们以这种方式丢失了与原始源的数据绑定。
所以这里的问题是我如何只返回我需要从转换器中的项目,以这种方式保持我的数据绑定到原始源,并允许双向绑定?
我不确定是否需要以下内容,但可能值得关注此应用程序的背景。此应用程序在选项卡控件中动态生成了选项卡,并且每个选项卡项都包含这些DataGrid中的一个。这些数据网格用相同的对象集合来填充,只是每个对象都有一个不同的过滤器,这取决于它包含在哪个标签中(这一切都与绑定到模型中)。转换器在那里很重要,因为向任何数据网格添加项目都需要一些额外的编码。
下面是一些代码来演示这个问题。
的XAML的DataGrid:
<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()方法,我的数据绑定并保持现有项目(这是有道理的,因为它只是引用对象的旧实例)。但是,当通过数据网格添加新项目时,应用程序中断时出现错误“双向绑定需要Path或XPath。”(这也是有意义的,因为它没有引用创建的新列表,而不是旧的可观察集合)。我该如何做到这一点,以便我仍然可以通过数据网格添加项目,以便通过新列表引用旧的可观察集合?
由于View支配虚拟机应该看起来像你的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
XAML:
<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>
此解决方案不起作用,因为您要永久移除数据源中的项目所有的数据网格都是从中绘制的。我只想从视图中删除它们。 – Chris
@Goody Gotcha,检查更新的答案。 – Karolis