c# - IMul​​tiValueConverter - INotifyPropertyChanged

标签 c# wpf datagrid combobox multibinding

我的要求有点烦人的问题,希望能解决。

假设您有以下类:

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 列表,其中包含给定的 Id1Id2 值以及一个 Sum 计算得到的值。

在我的 WPF 用户界面中,我有 2 ComboBoxes1 DataGrid。 1 ComboBox 保存有关 Id1 的信息,另一个保存有关 Id2 的信息。

现在在我的 DataGrid 中,我有一个 Foo 列表,其中显示了 2 列,其中一列显然是名称,但另一列现在让我很头疼。

第二列应显示 “正确的”FooB 类的 Sum 属性。

正确的 FooB 类由 UI 中的 2 个 ComboBox 和 SelectedItem 决定。

到目前为止我所做的是在我的 CodeBehind 中创建 2 个属性:(注意它们实际上有 backingfields 和指定的 PropertyChanged 我将代码减少到我的主要问题)

public int SelectedId1 { get; set; }
public int SelectedId2 { get; set; }

这两个属性绑定(bind)到相应的组合框:

<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 中的值并相应地更新信息时也能正常工作但是......当基础 Sum PropertyChanges 并收到 PropertyChanges 通知时,UI 不会更新。

如果我将列绑定(bind)到,它工作正常

<DataGridTextColumn Binding="{Binding FooBs[12].Sum}" />

你可以想象我不想在那里有索引,因为我需要通过 UI 中的组合框更新它。

希望你能帮帮我。

最佳答案

首先,我很难理解您当前的绑定(bind)表达式实际上是如何呈现总和,因为您的转换器 似乎只是返回FooB 对象本身,而不是它的 sum 属性 - 所以除非你在你的 FooB 类上有一个特定的 ToString() 实现格式化它以显示总和,我完全迷路了。

其次,我认为您的问题源于您的 MultiBinding 仅基于两个属性 - Data.SelectedId1Data.SelectedId2,因此,除非这两个属性中的任何一个发生变化,否则 MultiBinding 不会接收到 PropertyChanged 事件和更新。

您的结果的 sum 属性值的更改不是这两者中的任何一个,因此这很可能是 View 未更新的原因。

我绞尽脑汁寻找解决此问题的最佳方法,也许您应该在 ViewModel 中处理此问题,使用名为 CurrentFooB 的属性或您可以绑定(bind)的属性。然后,您可以在组合框的 SelectionChanged 事件处理程序中将此值设置为相应的 FooB 实例。

你的绑定(bind)看起来像这样:

<DataGrid ItemsSource={Binding Foos}>

    <DataGrid.Columns>

        <DataGridTextColumn Binding="{Binding Name}"/>
        <DataGridTextColumn Binding="{Binding CurrentFooB.Sum}"/>

    </DataGrid.Columns>

</DataGrid>

现在,假设 FooB 实现了 INotifyPropertyChanged,当当前找到的 FooB总和发生变化时,您的 View 应该更新。

编辑 1(尝试动态设置绑定(bind)源):

<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>

关于c# - IMul​​tiValueConverter - INotifyPropertyChanged,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22610610/

相关文章:

c# - Xml 数据到 WPF TreeView 的双向绑定(bind)

c# - 使用 vstest.consol.exe 运行 Moq 单元测试

c# - 跟随/剪辑到形状的文本?

c# - listview刷新时焦点不是 "holding"

c# - 防止在 DataGrid 中按下回车键时自动更改行

c# - 仅检索 FTP 文件名列表,没有其他详细信息

c# - WMI Code Creator for Bitlocker Status - 我哪里出错了?

c# - 为什么简单的 .Net Core 3.0 WPF 应用程序无法在部署计算机上启动

sql - 在 vb.net 中向 datagridview 添加更多行

WPF4 Datagrid 不对列标题进行排序