Binding enum with propertychanged handler not raising converter - c#

I'm not new in C# programming with WPF and I've never needed to do this, but now I need it and I'm stuck for some time now with it. I need to bind an enum that has attached it's OnPropertyChanged method to raise a converter every time the enum changes. I've got the following code for the enum:
private WindowState windowstate;
public enum WindowState
{
INITIAL = 0,
LANGUAGE = 1,
SENSOR = 2,
PARAMETERS = 3,
LEGAL = 4,
PRIVACY = 5,
ABOUT = 6,
MANUAL = 7
}
public WindowState State
{
get { return windowstate; }
set { windowstate = value; OnPropertyChanged("State"); }
}
And on the xaml where I bind the enum I've got this:
Color="{Binding State, Converter={StaticResource ButtonMenuColor}, ConverterParameter=language, ElementName=userControl}"
What I want is to change the color of a button depending on the value of the enum. Is it possible to make it this way or WPF, for some reason, does not support this?
This is the converter code:
class ButtonMenuColor : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Lynx.Windows.Herramientas.WindowState state = (Lynx.Windows.Herramientas.WindowState)value;
string param = parameter as string;
if (state.ToString().ToLower() == param)
return Application.Current.FindResource("white") as SolidColorBrush;
return Application.Current.FindResource("buttonmenu_color") as SolidColorBrush;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

what come into my head are :
change binding mode to two way. add updateSourceTrigger =
PropertyChanged , NotifySourceUpdated = True
try a fallback value checking your binding is correct or not.
maybe your control loads before your value set.
and put your enum value as
{x:static Namespace:Class.WindowState+LANGUAGE }

Seems you are binding to a user control, but your property is in a viewmodel?
So change your binding to
Color="{Binding DataContext.State, Conv...}"
So you are binding to the State property of your userControl's viewmodel. If the State is a DependencyProperty of your userControl the binding should work.

Related

Binding Visibility propety of text block to Stack.Any

I have a TextBlock as follow:
<TextBlock Text="You don't have any more items." Visibility="{binding}"
and in code behind I defined a Stack called items as follow:
private Stack<Item> _items;
How do I bind the text visibility in xaml to visible when _item.Any is false?
There are several steps to achieving what you want to do and they are all described here
You need to create a value converter similar to this;
public class EmptyCollectionToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var collection = (Stack<int>) value;
return collection.Any() ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then you need to add a reference to is in your resource dictionary in your xaml like this;
<views:EmptyCollectionToVisibilityConverter x:Key="EmptyCollectionToVisibilityConverter"/>
Finally bind your property in your view model to the visibility of your control and give the binding the converter like this;
Visibility="{Binding Items, Converter={StaticResource EmptyCollectionToVisibilityConverter}}"
Your property will probably need to be an observableCollection (which will mean changing the value converter example I gave you slightly.
I'd probably go with:
private Stack<Item> _items;
// bind to this property using converter
public bool IsVisible => !(_items?.Any(...) ?? false);
You shouldn't expose your _stack directly, but e.g. use methods to do something (because you need to rise notification every time you push/pop an item):
public void PushItem(Item item)
{
_items.Push(item);
OnPropertyChanged(nameof(IsVisible)); // implement INotifyPropertyChanged
}

WPF - Rendering a Xaml Segment

I am working on a WPF app. In this app, I have some XAML segments. I need to display the XAML segments in a TextBlock. In my XAML, I have the following line:
<TextBlock Text="{Binding Path=XamlSegment, Converter={StaticResource XamlToTextConverter}}" />
The XamlSegment property will have a value like "-0.275*x2". In an attempt to render this XAML in my UI so that the Superscript shows, I'm using the XamlToTextConverter, which is defined as follows:
namespace MyApp.Converters
{
public class XamlToTextConverter : IValueConverter
{
private static readonly Regex Regex = new Regex("(<.*?)>(.*)(</.*?>)", RegexOptions.Compiled);
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// value looks like this: -0.275*x<Run Typography.Variants="Superscript">2</Run>
var xamlText = value as string;
if (xamlText != null)
{
try
{
xamlText = "<TextBlock>" + xamlText + "</TextBlock>";
var xamlTextWithNamespace = Regex.Replace(xamlText, "$1 xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">$2$3");
return XamlReader.Parse(xamlTextWithNamespace);
}
catch (Exception)
{
return value;
}
}
else
{
return value;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
When this converter gets ran, my UI shows "System.Windows.Controls.TextBlock" instead of the rendered XAML. Yet, I don't know why. How do I get my XamlSegment to render in my UI?
Thanks
The Text property of the TextBlock will be set to a TextBlock object according to your XamlToTextConverter. Since the Text property should be type of string, it doesn't know how to show a TextBlock as string. So the default way to get thing done is to use the ToString method on TextBlock to fill the Text property, which makes the value of Text as "System.Windows.Controls.TextBlock".
It seems that you would like to dynamically render the xaml. You could reference this link(Loading XAML XML through runtime?) for a solution.

Why isn't my type converter working

Tearing my hair out here! I have this type-converter:
class CouponBarcodeToVisibilityConverterColumn : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (DesignerProperties.IsInDesignMode)
{
if ((string)parameter == "123456")
{
return Visibility.Visible;
}
return Visibility.Hidden;
}
if (value == null)
{
return Visibility.Visible;
}
var barcodesWanted = ((string)parameter).Split(System.Convert.ToChar("_"));
var actualBarcode = (string)value;
return barcodesWanted.Any(barcodeWanted => barcodeWanted == actualBarcode) ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
I have a UserControl with the following Resources section:
<UserControl.Resources>
<converters:CouponBarcodeToVisibilityConverterColumn x:Key="CouponBarcodeToVisibilityConverter1"/>
</UserControl.Resources>
I have a model called Bet, it looks like this:
public class Bet : INotifyPropertyChanged
{
//Lots of other stuff
private string _barcode;
public string Barcode
{
get { return _barcode; }
set
{
if (value == _barcode) return;
_barcode = value;
OnPropertyChanged("Barcode");
}
}
//Lots of other stuff
}
In the ViewModel which is the DataContext of my user control I have an Observable Collection of Bet. Back to my user control, I have a stack panel, the data context of which is the aforementioned Observable Collection.
Inside the Stack Panel I have a DataGrid, the ItemsSource property is simply {Binding}, deferring the binding up the tree as it were.
Inside my DataGrid I have this column:
<DataGridCheckBoxColumn x:Name="IsEwColumn" Binding="{Binding Wagers[0].IsEw,UpdateSourceTrigger=PropertyChanged}" Header="Each Way" Visibility="{Binding Path=Barcode, Converter={StaticResource CouponBarcodeToVisibilityConverter1}, ConverterParameter=123456}" Width="Auto"/>
The other element of the binding works perfectly (the checkbox is ticked whenever it is supposed to be) but my type converter is not. The breakpoint doesn't even get hit. The Barcode property inside Bet is definitely equal to 123456.
What have I missed?
What you have here is a list of bets for the items source of the data grid.
If you think about it
Bet1 could evaluate to visible when passed via type converter.
Bet2 could evaluate to visible when passed via type converter.
Bet3 could evaluate to collapsed when passed via type converter.
How would the datacolumn be both visible and collapsed at the same time.
You can't bind to visibility like that, unless you had an overall variable on the list or something that it could bind to.

wpf command control visibility

I have a custom command:
public static class CommandLibrary
{
private static RoutedUICommand cmdMyCommand = new RoutedUICommand("My command", "MyCommand", typeof(CommandLibrary));
public static RoutedUICommand MyCommand{ get { return cmdMyCommand ; } }
}
and I register a binding like this
CommandManager.RegisterClassCommandBinding(typeof(SomeClass), new CommandBinding(CommandLibrary.MyCommand, new ExecutedRoutedEventHandler(myCommandExecuteHandler), new CanExecuteRoutedEventHandler(myCommandCanExecuteHandler)));
And in generic.xaml I have a Buton with Command property set. The button is being properly enabled/disabled based on logic in myCommandCanExecuteHandler.
But now I would like to also control this button's visibility (independent of CanExecute which is mapped to IsEnabled). How do I approach that problem?
A discussion about the same problem is available here: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/c20782f8-2d04-49d3-b822-f77b4b87c27a/, but somehow the idea that CanBeSeen is a property of RoutedUICommand derived class does not appeal to me.
you can bind the the visibility attribute in xaml to the value which decides button's visibility
<Button Content="Button" Height="23" Visibility="{Binding someclass, Converter={Binding VisibitlityConverter}}"/>
and use a converter to convert bool value to callpsed or visible
class visibilityConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (bool)value == true? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
Do you want to make the button to be visible when the button is enabled/disabled... If then you have to bind the IsEnabled property to Visibility property using the Boolean to Visibility converter...
I ran into a very similar problem today.
"Sometimes" the CanExecute binding is being ignored when the visibility of the button is set collapsed state by the visibility converter. I said "sometimes" because, if I put a breakpoint in the visibility converter, it alters the behaviour.
When the visibility is changed to Visible - the CanExecute is not being called again. A mouse click anywhere on the UI refreshes the CanExecute binding, which makes it work as expected.
I worked around this issue by binding to the Button IsEnabled property directly to a property on my viewmodel, which reflects what my CanExecute does.

WPF Converter getting weird value from Binding

I have setup binding as follows
XAML
<TextBlock Text="{Binding Path=Color, Converter={StaticResource ColorToStringConverter}}" />
C#: Showing what Color is
public System.Windows.Media.Color Color
{
get
{
var color = new HSLColor { Hue = this.Hue, Saturation = this.Saturation, Luminosity = this.Luminosity };
string strColor = color.ToRGBString();
return new System.Windows.Media.Color {
R = byte.Parse(strColor.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
G = byte.Parse(strColor.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
B = byte.Parse(strColor.Substring(4, 2), System.Globalization.NumberStyles.HexNumber)
};
}
set { SetValue(ColorProperty, value); }
}
Converter
public class ColorToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Color color = (Color)value;
return color.ToString();
}
}
But my converter is getting value like
value = "{Name=0, ARGB=(0, 0, 0, 0)}"
I'd expect it to be a System.Windows.Media.Color why am I getting this?
Basically, I have 3 Silders for HSL values bound to DependencyProperties, each have a PropertyChangedCallback attached to them
new PropertyChangedCallback(HSLValuePropertyChanged)
It looks like
protected void HSLValueChanged()
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Color"));
}
Basically its purpose is to update controls bound to the dependency property Color. The idea is that get should run for property Color which creates a new color from HSL properties. The problem it seems is that the get does not run even when I change HSL values.
UPDATE
So I tried to return just value in the case of an exception, I got nothing in the textbox, so i did value.toString() got Color [Empty] all the time. What did I do wrong?
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
try
{
Color color = (Color)value;
return color.ToString();
} catch (Exception) {
return value.ToString();
}
}
You seem to be using the ColorDependencyProperty.
If so, I think the binding may never actually go trough the accessors (get/set) ...
You should set the new color (in the dependencyProperty via the setvalue method) on each of your H/S/L properties change call back...
I hope i am clear :-)
When bound on a DependencyProperty, bindings dont use property getters to obtain values, so, all the code you put in the Color property getter is skipped as far as bindings are concerned.
Stick to defining your getters as get { return (XXX)GetValue(MyProperty); } and find another way around.

Categories