我的要求有一个烦人的问题,希望可以解决。

假设您具有以下类别:

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类具有具有给定FooBId1值的Id2列表以及要计算的Sum值。

在我的WPF用户界面中,我有2 ComboBoxes1 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>

10-06 06:35