I have a checkable DropDownButton and a Grid.
I want to bind Button's IsChecked parameter with grid's Visibility value.
If (Visibility == Visible) IsCheked = true
I've tried to do like that:
IsChecked="{Binding ElementName=UsersDockWindow, Path=IsVisible}"
but it didn't work, cause IsVisible is readOnly property.
Use the BooleanToVisibilityConverter. Here's an example of how to do the binding using that converter.
Create a VisibilityToBooleanConverter and use that in your binding:
public class VisibilityToBooleanConverter : IValueConverter
{
public object Convert(object value, ...)
{
return (Visibility)value == Visibility.Visible;
}
}
In your XAML:
<Window.Resources>
<!-- assuming the local: xmlns is mapped to the appropriate namespace -->
<local:VisibilityToBooleanConverter x:Key="vbc" />
</Window.Resources>
IsChecked="{Binding Visibility,
ElementName=UsersDockWindow,
Converter={StaticResource vbc}}"
Related
I have successfully passed the following Enum to a Combobox using the following:
public enum Color
{
Blue,
Green,
Yellow
}
public Color _color { get; set; }
public Type Colors
{
get { return typeof(Color); }
}
In the view I have the following:
<ComboBox ItemsSource="{Binding Colors, Converter={StaticResource enumConverter}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding }" FontSize="14"/>
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This lets me pic a color in the box. What I want to do is to bind the chosen color to a property that's part of my viewmodel. I am very new to converters so I might be missing something.
You can bind the SelectedItem of the ComboBox to a property in your view model. The type of that property must match the type of the items generated by the enumConverter.
You can bind Combobox's SelectedItem to the property. I rename the Property to SelectedColor in the ViewModel. The PropertyChanged event is raised in the setter, so when you update the property, for example, from another method inside ViewModel, the view is notified and updated with the new value.
private Color _selectedColor;
public Color SelectedColor
{
get { return _selectedColor; }
set
{
_selectedColor = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("SelectedColor"));
}
}
}
And in the XAML
<ComboBox ItemsSource="{Binding Colors, Converter={StaticResource enumConverter}}"
SelectedItem="{Binding SelectedColor}">
...
I'm trying to make a custom converter that inherits from DependencyObject, but it doesn't work:
Converter:
public class BindingConverter : DependencyObject , IValueConverter
{
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(BindingConverter), new PropertyMetadata(null));
public object Convert(object value, Type targetType, object parameter, Globalization.CultureInfo culture)
{
Debug.Assert(Value != null); //fails
return Value;
}
public object ConvertBack(object value, Type targetType, object parameter, Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Xaml:
<StackPanel x:Name="this">
<!--works-->
<ContentControl Content="{Binding ActualHeight, ElementName=this}"/>
<!--doesn't work-->
<ContentControl>
<Binding>
<Binding.Converter>
<BindingConverter Value="{Binding ActualHeight, ElementName=this}" />
</Binding.Converter>
</Binding>
</ContentControl>
<TextBlock Text="{Binding Animals}"/>
</StackPanel>
Am I missing out anything?
I have some places in my projects where I needed similar functionality. Can't show you exact sample, just an idea:
perhaps you have to inherit from FrameworkElement, not IValueConverter, Something like this:
public class BindingHelper : FrameworkElement
in the BindingHelper class, set Visibility to Collapsed and IsHitTestVisible to false;
to make it working, insert it into visual tree directly. In your example, it should be a child of the StackPanel. So, it will have the same DataContext as other StackPanel children;
then, you can add one ore more dependency properties depending on your needs. For example, you might have single property for the source of data and some different properties which you then will use as converter return values. Handle all changes to the source property in your BindingHelper class and change output properties accordingly;
bind other controls to properties of the BindingHelper class using ElementName syntax
in Silverlight, ActualHeight and ActualWidth properties don't do notifications on property updates. So, binding to them won't work.
Note! ActualHeight property's binding is buggy on binding!
Why you inherit DependencyObject when coding a converter? You should just implement IValueConverter.
Try that,
First add MyConverter by the key of "MyConverterResource" on your resources then,
You can do than on XAML side or on cs side by
//You may do it on XAML side <UserControl.Resources>...
this.Resources.Add("MyConverterResource",new MyConverter());
<TextBlock Text="{Binding ActualHeight,ElementName=this
,Converter=MyConverterResource}"/>
public class MyConverter: IValueConverter
{
public object Convert(object value, Type targetType
, object parameter,Globalization.CultureInfo culture)
{
return "Your Height is:"+Value.toString();
}
}
Hope helps
I have ItemsControls with items binded from CollectionViewSource.
<ItemsControl ItemsSource="{Binding Source={StaticResource VisibleFlagsImageSourcePathView}}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<r:RibbonRadioButton SmallImageSource="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And another control outsite:
<TextBox Text="{Binding Path=SelectedCountryCode" />
What I am trying to accomplish is whenever I change the value of the TextBox I want the corresponding RibbonRadioButton property IsChecked set to true or false.
What you need to do is create a ViewModel with two properties.
class MyViewModel
{
// Bind this to TextBox
public String SelectedCountryCode { get; set; }
// Bind this to ItemsControl
public ObservableCollection<Object> VisibleFlagsImageSourcePath { get; set; }
}
// Note I have omitted implementation of `INotifyPropertyChanged`. But, you will need to implement it.
And monitor the SelectedCountryCode, and whenever it changes, change appropriate value in VisibleFlagsImageSourcePath collection.
Radio buttons represent enumerated values. A text box in this case would represent an open value. What you seem to want is a set of open values as well as a pre-set selection of enumerated values. The control that best represents this is a combo box.
If you decide to continue with the radio button/text box approach, you can adapt the method people use to bind radio buttons to an enumerated value, except use a string field/string field type converter instead of an enum field/enum field type converter.
See this answer for how to bind to enums: How to bind RadioButtons to an enum?
To adapt this to strings, simply make a class called KnownStringToBooleanConverter (note that this is an identical implementation to EnumToBooleanConverter):
public class KnownStringToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.Equals(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.Equals(true) ? parameter : Binding.DoNothing;
}
}
Also create a type with your known strings (similar to how you would create an enum):
public static class KnownCountryCodes
{
// Note: I'm guessing at these codes...
public const string England = "EN";
public const string Japan = "JP";
}
Then bind to this in a similar way:
<RadioButton IsChecked="{Binding Path=SelectedCountryCode, Converter={StaticResource KnownStringToBooleanConverter}, ConverterParameter={x:Static local:KnownCountryCodes.England}}" />
<RadioButton IsChecked="{Binding Path=SelectedCountryCode, Converter={StaticResource KnownStringToBooleanConverter}, ConverterParameter={x:Static local:KnownCountryCodes.Japan}}" />
If you want all your controls to cross-populate, then you'll need to implement INotifyPropertyChanged in your view model:
public class MyViewModel : INotifyPropertyChanged
{
// Bind this to TextBox and radio buttons. Populate the radio buttons manually
public string SelectedCountryCode
{
get
{
return selectedCountryCode;
}
set
{
selectedCountryCode = value;
RaiseNotifyPropertyChanged("SelectedCountryCode");
}
}
/* Todo: Implement NotifyPropertyChanged and RaiseNotifyPropertyChanged here */
private string selectedCountryCode;
}
When a custom value (that isn't in the list) is entered, the radio buttons will all dim. When you type in a value that is from the list, the corresponding radio button will light up. When you select a correct radio button, the value will be changed in the text box.
This View/ViewModel stuff is called MVVM.
See: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
I have a radiobutton group:
<TextBlock Height="24" Text="Update Interval (min):"/>
<RadioButton x:Name="radioButtonTimerNone" IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, Mode=TwoWay}"} Content="None" />
<RadioButton x:Name="radioButtonTimerOne" IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, Mode=TwoWay}"
Content="1" />
<RadioButton x:Name="radioButtonTimerFive" IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, Mode=TwoWay}"
Content="5" />
And a property:
public int UpdateInterval {
get { return _updateInterval; }
set { _updateInterval = value;
onPropertyChanged("UpdateInterval");
}
}
How do I bind the radiobuttons to the property, so radioButtonTimerNone is checked when UpdateInterval is 0, radioButtonTimerOne is checked when UpdateInterval is 1, etc.
I have tried to create a converter, but it doesn't identify which rb is being set:
[ValueConversion(typeof(RadioButton), typeof(bool))]
class UpdateIntervalToCheckedConverter : System.Windows.Data.IValueConverter
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
I expected 'value' to be a radiobutton, but it appears to be the value of UpdateInterval.
Thanks for any hints...
If you are using MVVM and are bound to a ViewModel (I would guess that you are), I usually consider my ViewModel to be a big ValueConverter. Why not put that logic into properties for each?
Here's an example of one of them:
public bool Timer5Enabled
{
get { return UpdateInterval == 5; }
}
And then you'd just bind to that:
<RadioButton
x:Name="radioButtonTimerOne"
IsChecked="{Binding Timer5Enabled, Mode=OneWay}"
Content="1" />
The only thing you'd need to change would be to tie your interval update logic to raise OnChanged for your dependent properties:
public int UpdateInterval {
get { return _updateInterval; }
set { _updateInterval = value;
onPropertyChanged("UpdateInterval");
onPropertyChanged("Timer5Enabled");
onPropertyChanged("...");
}
}
ValueConverters are good to avoid if you can.
Your value converter doesn't get told which RadioButton changed the value - all the binding knows is that the "IsChecked" property was changed, so the new value for IsChecked is the only thing it can tell the converter.
The first thing that springs to my mind is to supply a converter parameter with each of your bindings:
<RadioButton
x:Name="radioButtonTimerNone"
IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, ConverterParameter=0, Mode=TwoWay}"
Content="None" />
<RadioButton
x:Name="radioButtonTimerOne"
IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, ConverterParameter=1, Mode=TwoWay}"
Content="1" />
<RadioButton
x:Name="radioButtonTimerFive"
IsChecked="{Binding UpdateInterval, Converter={StaticResource updateIntervalToCheckedConverter}, ConverterParameter=5, Mode=TwoWay}"
Content="5" />
So now the "parameter" parameter on the "Convert" method will have the value "0", "1" or "5" depending on which RadioButton was checked. I think, though I'm not certain, that the parameter will be of type string, so you may have to take that into account when interrogating the value.
You could probably consider having a List<...> with different intervals. The list type should preferably be some custom type (e.g. UpdateInterval) or a KeyValuePair<K,V> to decouple what is shown to the user from what is an actual value.
Then you could have a ListBox bound to this list, and each ListBoxItem templated to show a RadioButton. Then, in the template, you bind radio button's IsChecked to ListBoxItem.IsSelected.
The final touch is just to bind your property to the ListBox's SelectedItem or SelectedValue.
This has been a very annoying problem for me.
The WPF RadioButton class has a bug that removes the binding for the IsChecked property when you assign multiple RadioButtons to the same GroupName. People have given many work arounds, but when I had to visit this again I came up with one that doesn't make me queasy.
So what you have to do is subclass the RadioButton class with this:
public class RadioButton: System.Windows.Controls.RadioButton
{
protected override void OnClick()
{
base.OnClick();
SetValue(CurrentValueProperty,CheckedValue);
}
public int CurrentValue
{
get { return (int)GetValue(CurrentValueProperty); }
set { SetValue(CurrentValueProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentValueProperty =
DependencyProperty.Register("CurrentValue", typeof(int), typeof(RadioButton), new FrameworkPropertyMetadata(0,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, CurrentValue_Changed));
public static void CurrentValue_Changed(object sender, DependencyPropertyChangedEventArgs e)
{
((RadioButton)sender).IsChecked = ((RadioButton)sender).CurrentValue == ((RadioButton)sender).CheckedValue;
}
public int CheckedValue
{
get { return (int)GetValue(CheckedValueProperty); }
set { SetValue(CheckedValueProperty, value); }
}
// Using a DependencyProperty as the backing store for CheckedValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CheckedValueProperty =
DependencyProperty.Register("CheckedValue", typeof(int), typeof(RadioButton), new UIPropertyMetadata(0));
}
All this does is add two dependency properties so you can do an equality comparison.
So in XAML an example would be this:
<UserControl x:Class="MyClass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:MVVMLibrary;assembly=MVVMLibrary"
Height="Auto" Width="Auto">
<c:RadioButton CurrentValue="{Binding MyValue}" CheckedValue="1" GroupName="SearchType" >Value 1</c:RadioButton>
<c:RadioButton Grid.Column="1" CurrentValue="{Binding MyValue}" CheckedValue="2" GroupName="SearchType" >Value 2</c:RadioButton>
</UserControl>
So If you notice all you do is
1) Bind to the CurrentValue property
2) Set the CheckedValue property to the value that would make the RadioButton checked
3) Set the RadioButtons to the same GroupName
If you notice i made CurrentValue and CheckedValue int type. The reason I did this is so that you could actually bind CurrentValue to an enumeration. I think this is awesome, but that's just my opinion which probably doesn't count for much. :)
Hope this helps somebody.
One possibility is to implement an IValueConverter and configure it passing the expected enumeration value for every RadioButton you need to bind, as I described here in my blog.
I am using the tree view control in my silverlight project. I use data binding for binding my model to the tree. This works perfect.
After adding some features to the tree I ran into two problems:
When I change a property on my Model, the tree does not get updated, even after my onproperty changed get called and also my converter is not called?(I need to hide the item when a specific property changes) (Answered)
How do I hide an Item in the tree? (I use Textbox + image as Item template)
Stack panel is hidden, but empty container remains in tree
DataTemplate:
<common:HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal" Visibility="{Binding IsAvailable, Converter={StaticResource ItemVisibleConverter} ,Mode=TwoWay}" >
<Image Source="{Binding Converter={StaticResource ImageConverter}}"/>
<controls:Label Name="myItem" Content="{Binding Description, Converter={StaticResource ItemConverter} ,Mode=TwoWay}" Foreground="Black"/>
</StackPanel>
</common:HierarchicalDataTemplate>
Converter:
public object Convert(object value, Type targetType, object parameter, ystem.Globalization.CultureInfo culture)
{
return GetVisibility(value);
}
private Visibility GetVisibility(object value)
{
bool IsVisible= (bool)value;
if (IsAvailableForDownload)
{
return Visibility.Visible;
}
else
{
return Visibility.Collapsed;
}
}
Model
public class MyModel: INotifyPropertyChanged
{
public bool IsAvailable
{
get
{
return _IsAvailableForDownload;
}
set
{
_IsAvailableForDownload = value;
onPropertyChanged(this, "IsAvailableForDownload");
}
}
//Code for on property changed event
}
Regards
You probably need to make sure that your model implements INotifyPropertyChanged so that the binding system can do its job.
Could you have a property of type Visibility that your item template binds to, or a bool plus a value converter that returns a Visibility value?
<DataTemplate>
<Grid Visibility="{Binding ThisThingsIsVisible}">
<Button Content="{Binding Blah}" />
</Grid>
</DataTemplate>
I don't know if this is the recommended way or not - could your bound object not expose hidden items in their collections?