【问题标题】:How to override ToString() and bind it to WPF如何覆盖 ToString() 并将其绑定到 WPF
【发布时间】:2016-01-25 13:09:14
【问题描述】:

我尝试将 mycollection 绑定到 wpf:

    private ObservableCollection<MyClass> _coll;

    public ObservableCollection<MyClass> Coll
    {
        get
        {
            if (_coll == null)
                _coll = new ObservableCollection<MyClass>();                
            return _coll;
        }

        set
        {       
            _coll = value;
        }           
    }

MyClass:

 class MyClass 
  {
     int Id;
     String Name1;
     String Name2;
  }

在 WPF:

 <ListBox Grid.Row="1" x:Name="lbKey" BorderBrush="Gray"
                                     ItemsSource="{Binding  Path=Coll}"
                                     ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                                     HorizontalContentAlignment="Stretch"
                                     ItemContainerStyle="{StaticResource ResourceKey=lbStyle}">
                                <ListBox.ItemTemplate>
                                    <DataTemplate>
                                        <Border BorderThickness="1" BorderBrush="LightGray" Background="WhiteSmoke"
                                                HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
                                            <TextBlock Text="{Binding}" TextWrapping="Wrap" Margin="2"
                                                       Background="Transparent"
                                                       HorizontalAlignment="Stretch"/>
                                        </Border>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                            </ListBox>

但是,当我运行程序时,会看到类似 Id.ToString(); 所以,我必须重写 ToString() 方法,但我不能改变 MyClass 方法。

我创建了扩展方法:

namespace Some.Name.Space
{
   public static class MyClassExtensions
     {
       public static string ToString(this MyClass my)
        {
          return String.Format("{0} {1}"my.Name1,my.Name2);
        }
      }
}

但这对我没有帮助:我看到我的网格字符串是这样的:1,2 等等。

你能告诉我,如何在扩展方法中重写 ToString 方法并将其绑定到 WPF 中。

【问题讨论】:

  • 另请注意,您的 MyClass 字段是私有的,您的扩展方法甚至不会编译,因为这些字段是私有的,您无法访问它们,因此您无法覆盖 ToString() 以返回格式化的除非你诉诸反射,否则你说你想要的字符串。

标签: c# wpf data-binding extension-methods


【解决方案1】:

扩展方法不要覆盖ToString() 方法,因为这里有详细信息: How to create extension method for toString?

但是..

您不必重写ToString() 方法。你正在绑定,但你没有指出哪个属性可以被绑定。

改变这个:

<TextBlock Text="{Binding}" TextWrapping="Wrap" Margin="2"
                                                       Background="Transparent"
                                                       HorizontalAlignment="Stretch"/>

到这里

<TextBlock Text="{Binding Name1}" TextWrapping="Wrap" Margin="2"
                                                       Background="Transparent"
                                                       HorizontalAlignment="Stretch"/>

然后您可以精确绑定Name1 属性的值。

而且您还必须更改MyClass(您必须拥有公共财产或字段)

      public class MyClass 
      {
          int Id;
          private string _Name1;
          private string _Name2;

          public string Name1
          {
           get { return _Name1; }
           set { _Name1 = value; }
          }

          public string Name2
          {
           get { return _Name2; }
           set { _Name2 = value; }
          }
       }

但是...

如果您想要像这样Text="{Binding} 绑定并且想要您自己的显示 MyClass 实现 - 您必须像这样覆盖 MyClass 中的 ToString 方法:

      class MyClass 
      {
         int Id;
         String Name1;
         String Name2;

         public override string ToString()
         {
           return String.Format("{0} {1}", this.Name1, this.Name2);
         }
     }

这样做是很好的模式。

但是如果您不能更改 MyClass - 您可以创建自己的类型并使用 in 打包 MyClass

          public class NewMyClass 
          {
             public MyClass myclass {get;set;}

             public override string ToString()
             {
               return String.Format("{0} {1}", mycalss.name1, mycalss.name2);
             }
         }

改变

public ObservableCollection<NewMyClass> Coll

在这个解决方案中你的 xaml 是正确的

但是

如果MyClass 有私有字段,例如 You show where is no way to get the fields to display.

【讨论】:

  • 请注意String Name1; 不是属性,而是字段。为了绑定到它,它必须是公共属性,例如public string Name1 { get; set; }
  • 我无法更改 MyClass...:(
  • 构建自己的类型。 public MyNewClass { public MyClass myclass {get;set; } }Create ToString 覆盖。下一个public ObservableCollection&lt;MyNewClass&gt; Coll
  • 我改变我的答案给你一个例子
【解决方案2】:

我认为这种情况下更好的选择是创建为您提供组合名称的属性。您可以像这样定义该属性:

 public string DisplayName
  {
     get { return _Name1 + _Name2; }
  }

这样绑定的代码会是这样的:

<TextBlock Text="{Binding DisplayName}" TextWrapping="Wrap" Margin="2" ../>

或者整个类的定义如下:

    class MyClass
    {
        public int Id { get; set; }
        private string _Name1;
        private string _Name2;

        public string Name2
        {
            get { return _Name2; }
            set { _Name2 = value; }
        }
        public string Name1
        {
            get { return _Name1; }
            set { _Name1 = value; }
        }
        public string DisplayName
        {
            get { return _Name1 + _Name2; }
        }
    }

这不是确切问题的答案,但这会很好地解决问题。

【讨论】:

  • 有 2 个 Name1 属性。
  • @goodeinstein:好地方,那是错误的,我已经更新了我的答案。谢谢......!
  • 您是否注意到 OP 说“但我无法更改 MyClass 方法。”我认为这意味着 OP 无权修改 MyClass 所以这是非常无效的答案。
  • @JanneMatikainen:如何覆盖 ToSring() 而无需修改 MyClass ?
  • 使用 ValueConverter 并通过反射挖掘出私有字段值,并像在扩展方法中一样格式化字符串。
【解决方案3】:

首先创建一个 ValueConverter,它将 MyClass 实例作为参数并从类型中挖掘私有字段,然后获取这些字段的值以返回正确的字符串。

public class MyClassToStringValueConverter : IValueConverter
{
    private static FieldInfo Name1Field;
    private static FieldInfo Name2Field;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (Name1Field == null)
        {
            Name1Field = typeof(MyClass).GetField("Name1", BindingFlags.NonPublic | BindingFlags.Instance);
        }

        if (Name2Field == null)
        {
            Name2Field = typeof(MyClass).GetField("Name2", BindingFlags.NonPublic | BindingFlags.Instance);
        }

        return string.Format("{0} {1}", Name1Field.GetValue(value), Name2Field.GetValue(value));
    }

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

在您的 xaml 中,创建此 ValueConverter 的资源并在绑定中使用它,下面是绑定到视图模型中 MyClass 类型的 MyClassProperty 的示例。

<Window.Resources>
    <local:MyClassToStringValueConverter x:Key="MyClassToStringValueConverter"/>
</Window.Resources>

<TextBox Text="{Binding MyClassProperty, Converter={StaticResource MyClassToStringValueConverter}}"/>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多