Reputation: 537
I am pretty new to C# and WPF framework,my question might sound silly. I am using the two-way binding feature. So I implement INotifyPropertyChanged interface. I have a property named DisplayFormat, so whenever the format changes from Binary to Hex, my text should convert accordingly. My question is where should I include the code/logic for the conversion between Binary and decimal?
[DefaultValue(displayFormat.Binary)]
public displayFormat DisplayFormat
{
get { return this.format; }
set { this.format = value; OnPropertyChanged("DisplayFormat"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
Upvotes: 3
Views: 893
Reputation: 61369
Another converter approach would be to use a MultiValueConverter. This does not require the dependency property or additional NotifyPropertyChanged. The important thing to know about MultiValueConverter is that you get the "values" in the order that you put them in XAML.
The converter becomes:
public class NumberToSpecialStringConverter : IMultiValueConverter
{
public Convert(...)
{
//This is going to the UI, from the Model
return (value[1] as DisplayFormat).Convert(value[0]); //Or whatever you have
}
public ConvertBack(...)
{
//This is going to the Model, from the UI
return (value[1] as DisplayFormat).ConvertBack(value[0]); //Or whatever you have
}
}
The XAML:
<Window.Resources>
<local:NumberToSpecialStringConverter x:Key="FormatConverter"/>
</Window.Resources>
...
<TextBlock>
<MultiBinding Converter="{StaticResource FormatConverter}">
<Binding Path="MyValue"/>
<Binding Path="DisplayFormat"/>
</MultiBinding>
</TextBlock>
No other changes are required.
Upvotes: 2
Reputation: 149608
What can be done is have two properties, both binded to your DisplayFormat
property. When a Hex value should be presented, you may set the visibility of the Binary content control (maybe a TextBlock
) to false and only present your Hex values TextBlock
, and the other way around for Binary values. This can be achieved using an EventTrigger
on the NotifyPropertyChanged
of DisplayFormat
.
Another approach would be to use a IValueConverter
on your DisplayFormat
property and have the logic for checking Hex or Binary and returning the proper format. That way you may present tge appropriate format for each value.
A possible IValueConverter implementation:
public class BinaryOrHexConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
int result;
return int.TryParse(inputString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out result) ? result.ToString() : value.ToString() // Assuming default is binary
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
Upvotes: 1
Reputation: 61369
Whenever you need to convert something to something else, you use a converter. A converter is just a class that implements IValueConverter
.
public class NumberToSpecialStringConverter : IValueConverter
{
...
}
Converters take two inputs, the value (whatever is actually displayed or bound to) and a parameter. The parameter can be whatever you want, but cannot be bound. Since you want a bound parameter, we need to inherit from DependencyObject
as well and declare a DependencyProperty
to bind to:
public class NumberToSpecialStringConverter : DependencyObject, IValueConverter
{
public displayFormat CurrentFormat
{ //Dependency property stuff }
//Other DP stuff, use the 'propdp' snippet to get it all, or look on MSDN
public Convert(...)
{
//This is going to the UI, from the Model
return displayFormat.Convert(value); //Or whatever you have
}
public ConvertBack(...)
{
//This is going to the Model, from the UI
return displayFormat.ConvertBack(value); //Or whatever you have
}
}
Now that you have that, you just need to declare and use it:
<Window.Resources>
<local:NumberToSpecialStringConverter x:Key="FormatConverter" CurrentFormat="{Binding DisplayFormat}"/>
</Window.Resources>
...
<TextBlock Text="{Binding Path=MyValue, Converter={StaticResource FormatConverter}"/>
There is one more catch. Changing "DisplayFormat" will cause NotifyPropertyChanged to fire, which will update the value inside the converter. However, the UI isn't running the convert function because it doesn't think anything has changed. Thus, you need to "pretend" that the value changed by invoking its NotifyPropertyChanged as well:
[DefaultValue(displayFormat.Binary)]
public displayFormat DisplayFormat
{
get { return this.format; }
set
{
this.format = value;
OnPropertyChanged("DisplayFormat");
OnPropertyChanged("MyValue");
}
}
Now the UI will perform a fresh "get" and conversion and display what you wanted!
Upvotes: 1