I try to bind mycollection into 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;
}
And at 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>
But, when i run program see something like Id.ToString(); So, i have to override ToString() method ,but i can not change MyClass methods.
And i create extension method:
namespace Some.Name.Space
{
public static class MyClassExtensions
{
public static string ToString(this MyClass my)
{
return String.Format("{0} {1}"my.Name1,my.Name2);
}
}
}
But this is not help to me: i see at my grid strings like this: 1,2 and so on.
Can you tell me, how to override ToString methods at extended method and bind it into WPF.
Extension method don't override ToString()
method because details here: How to create extension method for toString?
BUT..
You don't have to override ToString()
method. You are binding but you do not point which property may by bind.
Change this:
<TextBlock Text="{Binding}" TextWrapping="Wrap" Margin="2"
Background="Transparent"
HorizontalAlignment="Stretch"/>
To this
<TextBlock Text="{Binding Name1}" TextWrapping="Wrap" Margin="2"
Background="Transparent"
HorizontalAlignment="Stretch"/>
Then You can bind exactly value of Name1
property.
and You must also change MyClass
(you have to have public property nor fields)
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; }
}
}
BUT...
If You want bind like this Text="{Binding}
and You want Your own implementation of display MyClass - You have to override ToString
method in MyClass like this:
class MyClass
{
int Id;
String Name1;
String Name2;
public override string ToString()
{
return String.Format("{0} {1}", this.Name1, this.Name2);
}
}
It is good patern to do this.
BUT if You can not change MyClass - You can create Your own type and pack MyClass with in
public class NewMyClass
{
public MyClass myclass {get;set;}
public override string ToString()
{
return String.Format("{0} {1}", mycalss.name1, mycalss.name2);
}
}
and change
public ObservableCollection<NewMyClass> Coll
in this solution Your xaml is correct
BUT
If MyClass
have private fields like You show where is no way to get that fields to dispaly.
I think the better option for this scenario is to create property that gives you a combined name. You can define that property as like this:
public string DisplayName
{
get { return _Name1 + _Name2; }
}
So that the binding code will be similar to this:
<TextBlock Text="{Binding DisplayName}" TextWrapping="Wrap" Margin="2" ../>
Or the whole class definition will be like the following:
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; }
}
}
This is not the answer to the exact question but This will solve the issue in a pretty good manner.
First create a ValueConverter that will take the MyClass instance as a parameter and dig the private fields from the type and then get the values of those fields to return the correct string.
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();
}
}
In your xaml, create a resource of this ValueConverter and use it in the binding, below is an example that binds to MyClassProperty of type MyClass in the viewmodel.
<Window.Resources>
<local:MyClassToStringValueConverter x:Key="MyClassToStringValueConverter"/>
</Window.Resources>
<TextBox Text="{Binding MyClassProperty, Converter={StaticResource MyClassToStringValueConverter}}"/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.