在WPF中,我如何动态更改DataGridTextColumn绑定中的转换器?

3

我真的不理解WPF和XAML,并且继承了一些写得非常糟糕的代码,所以我的翻译可能不太准确,但我会尽力。

我继承了一个数据网格(DataGrid),它在代码后台绑定到一个人(Person)对象的列表中,在XAML中指定必要的DataGridTextColumns(数据网格文本列)(可能是为了允许样式化)。

<DataGrid x:Name="PersonGrid" ItemsSource="{Binding}" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Path=LastName}" MaxWidth="Infinity" MinWidth="150" Header="Last Name">
        <DataGridTextColumn Binding="{Binding Path=FirstName}" MaxWidth="Infinity" MinWidth="150" Header="First Name" />
        <DataGridTextColumn Binding="{Binding Path=DOB, StringFormat=\{0:MM/dd/yyyy\}}" MaxWidth="Infinity" MinWidth="200" Header="Date of Birth (MM/DD/YYYY)" />
        <DataGridTextColumn Binding="{Binding Path=Number}" MaxWidth="Infinity" MinWidth="150" Header="(P)erson Number" />
    </DataGrid.Columns>
    <DataGrid.DataContext>
        <dm:Person />
    </DataGrid.DataContext>
</DataGrid>

我希望能够显示一个人的姓氏首字母,根据复选框的状态可以选择是否显示。
<CheckBox Name="ShowFullNames_CheckBox" Content="Show Full Names" IsChecked="False"/>

我能够在代码后端将转换器与 LastName 绑定连接起来,但是当我尝试在数据绑定后更改该转换器时,会出现错误(“绑定在使用后无法更改”)。
我认为也许我可以将复选框的 IsChecked 状态绑定到 ConverterParameter 或 Multibinding 的一个绑定上,但是无法使其正常工作。
<DataGridTextColumn MaxWidth="Infinity" MinWidth="150" Header="Last Name">
    <DataGridTextColumn.Binding>
        <MultiBinding Converter="myStringTruncator">
            <Binding Source="ShowFullNames_CheckBox" Path="IsChecked"/>
            <Binding Path="LastName"/>
        </MultiBinding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>

在我的StringTruncator类的Convert方法中,第一个绑定只填入了DependencyProperty.UnsetValue,而没有将复选框的值填入。
可能有一种我没注意到的非常简单的方法。你有什么想法吗?

正如您从答案中看到的,问题出在绑定上。为了更好地理解绑定的作用,您可以在绑定上设置PresentationTraceSources.TraceLevel="High",它将向您显示一堆有用的信息(并且它可能已经指出没有找到名为ShowFullNames_CheckBoxSource)。 这是调试问题的非常好的方法,特别是对于继承的应用程序来说;-) - RoelF
1个回答

4
您可以在XAML中将转换器添加到绑定中。
<DataGridTextColumn Binding="{Binding Path=LastName, Converter={StaticResource YourConverter}"
                    MaxWidth="Infinity"
                    MinWidth="150"
                    Header="Last Name">

如果要绑定复选框的状态,您需要使用类似以下内容的代码(未经测试)

<DataGridTextColumn Header="Last Name">
  <DataGridTextColumn.Binding>
    <MultiBinding Converter="{StaticResource NameAndCheckBoxMultiValueConverter}">
      <Binding Path="LastName" />
      <Binding ElementName="myCheckBox" Path="IsChecked" />
    </MultiBinding>
  </DataGridTextColumn.Binding>
 </DataGridTextColumn>

转换器:

  using System;
    using System.Globalization;
    using System.Windows.Data;

    namespace TestWpf
    {
        public class NameAndCheckBoxMultiValueConverter: IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
            var lastName = values[0] as String;
            if(lastName != null)
            {
                var isChecked = (bool)values[1];
                if (isChecked)
                {
                    return lastName.Substring(0,1);
                }
                return lastName;
            }
            return null;
            }

            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }

1
你可以将它放在<UserControl.Resources />中。回答主题:克隆绑定以在运行时分配转换器https://dev59.com/jHVD5IYBdhLWcg3wRpeX#14740448 - user3411327
1
你需要在文件头中添加命名空间声明,例如:xmlns:testWpf="clr-namespace:TestWPF"。然后添加转换器:<UserControl.Resources><testWpf:MyMultiValueConverter x:Key="NameAndCheckBoxMultiValueConverter" /></UserControl.Resources>。这样有帮助吗? - user3411327
1
我从来没有在另一个类中嵌套转换器。刚刚发现,这是不可能的:https://dev59.com/B2855IYBdhLWcg3wj1MS#4270348 - user3411327
我快被这个问题搞疯了。在办公室的三台电脑上,这段代码运行得很好。但是在现场安装到四台电脑上时失败了。CheckBox 没有绑定到多绑定,所以我一直得到一个类型为 MS.Internal.NamedObject 的错误信息。我怀疑这是一些默认的未绑定绑定对象。我找不出这些电脑之间有任何区别,并且不知道如何追踪问题。你有什么想法,为什么绑定可能没有生效? - Michael Repucci
在这里发布问题:http://stackoverflow.com/questions/22536645/what-hardware-platform-difference-could-cause-an-xaml-wpf-multibinding-to-checkb,并且得到了答案。这是.NET Framework 4中的一个漏洞。安装.NET 4.5.1可以解决此问题。 - Michael Repucci
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接