如何覆盖 ToString() 并将其绑定到 WPF
How to override ToString() and bind it to WPF
我尝试将 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 中吗?
扩展方法不要覆盖 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 属性 或字段)
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
有私有字段,例如您在何处显示无法显示该字段。
我认为这种情况下更好的选择是创建 属性 为您提供组合名称。您可以这样定义 属性:
public string DisplayName
{
get { return _Name1 + _Name2; }
}
这样绑定代码将类似于:
<TextBlock Text="{Binding DisplayName}" TextWrapping="Wrap" Margin="2" ../>
或者整个 class 定义如下:
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; }
}
}
这不是确切问题的答案,但这会很好地解决问题。
首先创建一个 ValueConverter,它将 MyClass 实例作为参数并从类型中挖掘私有字段,然后将这些字段的值获取到 return 正确的字符串。
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}}"/>
我尝试将 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 中吗?
扩展方法不要覆盖 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 属性 或字段)
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
有私有字段,例如您在何处显示无法显示该字段。
我认为这种情况下更好的选择是创建 属性 为您提供组合名称。您可以这样定义 属性:
public string DisplayName
{
get { return _Name1 + _Name2; }
}
这样绑定代码将类似于:
<TextBlock Text="{Binding DisplayName}" TextWrapping="Wrap" Margin="2" ../>
或者整个 class 定义如下:
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; }
}
}
这不是确切问题的答案,但这会很好地解决问题。
首先创建一个 ValueConverter,它将 MyClass 实例作为参数并从类型中挖掘私有字段,然后将这些字段的值获取到 return 正确的字符串。
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}}"/>