我的要求有一个烦人的问题,希望可以解决。
假设您具有以下类别:
public class Foo
{
public string Name { get; set; }
public List<FooB> FooBs { get; set; }
}
public class FooB
{
public int Id1 { get; set; }
public int Id2 { get; set; }
public decimal Sum { get; set; }
}
现在,
Foo
类具有具有给定FooB
和Id1
值的Id2
列表以及要计算的Sum
值。在我的WPF用户界面中,我有
2 ComboBoxes
和1 DataGrid
。1 ComboBox包含有关
Id1
的信息,另一个包含有关Id2
的信息。现在在我的DataGrid中,我显示了一个由2列显示的
Foo
列表,一个显然是名称,但是另一个现在让我头疼。第二列应显示
Sum
类的"correct" FooB
属性。正确的FooB类由UI中的2个ComboBoxes以及SelectedItem确定。
到目前为止,我要做的是在CodeBehind中创建2个Properties:(注意,它们实际上已经指定了backingfields和PropertyChanged,所以我将代码简化为主要问题)
public int SelectedId1 { get; set; }
public int SelectedId2 { get; set; }
这两个属性绑定到相应的ComboBox:
<c1:C1ComboBox ItemsSource="{Binding Id1s}"
SelectedItem="{Binding SelectedId1}" />
<c1:C1ComboBox ItemsSource="{Binding Id2s}"
SelectedItem="{Binding SelectedId2}" />
到目前为止,我的DataGrid看起来像这样:
<local:BindingProxy x:Key="BindingProxy"
Data="{Binding}" />
<DataGrid ItemsSource={Bindings Foos}>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTextColumn>
<DataGridTextColumn.Binding>
<MultiBinding Converter="{StaticResource GetCorrectFooB}">
<Binding Binding="."></Binding>
<Binding Binding="Data.SelectedId1"></Binding>
<Binding Binding="Data.SelectedId2"></Binding>
</MultiBinding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
(请注意,BindingProxy来自此处:http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/-允许从DataGridRow的DataContext中的窗口获取数据)
转换器看起来像这样:
public class GetCorrectFooB : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var foo = (Foo)values[0];
var id1 = (int) values[1];
var id2 = (int) values[2];
return foo.FooBs.First(x => x.Id1 == id1 && x.Id2 == id2).Sum;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
目前,这很好用,甚至当我更改UI中的2个ComboBox中的值并相应地更新信息时,行为仍然正确...但是,当基础总和PropertyChanges并由PropertyChanges通知时,UI不会更新。
如果我只将列绑定到它的工作正常
<DataGridTextColumn Binding="{Binding FooBs[12].Sum}" />
您可以想象我不想在那里有一个索引,因为我需要通过UI中的ComboBoxes更新它。
希望你能帮助我。
最佳答案
首先,我正在努力了解您当前的绑定表达式实际上是如何显示和,因为您的转换器似乎只是返回FooB对象本身,而不是sum属性-因此,除非您有特定的ToString()实现在格式化它以显示总和的FooB类上,我完全迷路了。
其次,我认为您的问题源于以下事实:MultiBinding仅基于两个属性-Data.SelectedId1和Data.SelectedId2,因此,除非这两个属性中的任何一个发生更改,否则MultiBinding都不会接收PropertyChanged事件和更新。
结果的sum属性的值更改既不是这两者,因此这很可能就是未更新视图的原因。
作为解决此问题的最佳方法,我正在绞尽脑汁,也许您应该只在ViewModel中处理它,并拥有一个名为CurrentFooB的属性或可以绑定的属性。然后,您可以在组合框的SelectionChanged事件处理程序中将此值设置为对应的FooB实例。
您的绑定将类似于:
<DataGrid ItemsSource={Binding Foos}>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"/>
<DataGridTextColumn Binding="{Binding CurrentFooB.Sum}"/>
</DataGrid.Columns>
</DataGrid>
现在,假设FooB实现了INotifyPropertyChanged,则当当前找到的FooB的总和发生更改时,您的视图应会更新。
编辑1(尝试动态设置绑定源):
<DataGrid ItemsSource={Binding Foos}>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"/>
<DataGridTextColumn>
<DataGridTextColumn.Binding>
<Binding Path="Sum">
<Binding.Source>
<MultiBinding Converter="{StaticResource GetCorrectFooB}">
<Binding Binding="."></Binding>
<Binding Binding="Data.SelectedId1"></Binding>
<Binding Binding="Data.SelectedId2"></Binding>
</MultiBinding>
</Binding.Source>
</Binding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>