You can further simplify the accepted answer. Instead of typing out the enums as strings in xaml and doing more work in your converter than needed, you can explicitly pass in the enum value instead of a string representation, and as CrimsonX commented, errors get thrown at compile time rather than runtime:
ConverterParameter={x:Static local:YourEnumType.Enum1}
<StackPanel>
<StackPanel.Resources>
<local:ComparisonConverter x:Key="ComparisonConverter" />
</StackPanel.Resources>
<RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:YourEnumType.Enum1}}" />
<RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:YourEnumType.Enum2}}" />
</StackPanel>
Then simplify the converter:
public class ComparisonConverter : 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) == true ? parameter : Binding.DoNothing;
}
}
Edit (Dec 16 '10):
Thanks to anon for suggesting returning Binding.DoNothing rather than DependencyProperty.UnsetValue.
Note - Multiple groups of RadioButtons in same container (Feb 17 '11):
In xaml, if radio buttons share the same parent container, then selecting one will de-select all other's within that container (even if they are bound to a different property). So try to keep your RadioButton's that are bound to a common property grouped together in their own container like a stack panel. In cases where your related RadioButtons cannot share a single parent container, then set the GroupName property of each RadioButton to a common value to logically group them.
Edit (Apr 5 '11):
Simplified ConvertBack's if-else to use a Ternary Operator.
Note - Enum type nested in a class (Apr 28 '11):
If your enum type is nested in a class (rather than directly in the namespace), you might be able to use the '+' syntax to access the enum in XAML as stated in a (not marked) answer to the question :
ConverterParameter={x:Static local:YourClass+YourNestedEnumType.Enum1}
Due to this Microsoft Connect Issue, however, the designer in VS2010 will no longer load stating "Type 'local:YourClass+YourNestedEnumType' was not found."
, but the project does compile and run successfully. Of course, you can avoid this issue if you are able to move your enum type to the namespace directly.
Edit (Jan 27 '12):
If using Enum flags, the converter would be as follows:
public class EnumToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return ((Enum)value).HasFlag((Enum)parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.Equals(true) ? parameter : Binding.DoNothing;
}
}
Edit (May 7 '15):
In case of a Nullable Enum (that is **not** asked in the question, but can be needed in some cases, e.g. ORM returning null from DB or whenever it might make sense that in the program logic the value is not provided), remember to add an initial null check in the Convert Method and return the appropriate bool value, that is typically false (if you don't want any radio button selected), like below:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null) {
return false; // or return parameter.Equals(YourEnumType.SomeDefaultValue);
}
return value.Equals(parameter);
}
Note - NullReferenceException (Oct 10 '18):
Updated the example to remove the possibility of throwing a NullReferenceException. `IsChecked` is a nullable type so returning `Nullable` seems a reasonable solution.
Short answer: what you want to do cannot be done directly in XAML, but there are other ways to do it.
Long answer: the ComboBox looks for the TextSearch.Text property directly on the data items stored in the Items or ItemsSource collection. Therefore, you can't set the property in the data template or style because they apply to the objects used to display the data items, and not the data items themselves.
In particular, if you look at the examples on the TextSearch class page, you will see that they attach the TextSearch.Text property to the Image objects which go into the ComboBox.Items collection. You could do this in your program by making Person a DependencyObject, but I don't think you want to set the property on every single object like that.
You have several options here:
If you can modify the Person class, you can either define the ToString() method to return the text to autocomplete on or define an arbitrary property like Fullname and set Textsearch.TextPath on the ComboBox. For example:
public class Person
{
string FirstName { get; set; }
string LastName {get; set; }
string FullName { get { return String.Format("{0} {1}", FirstName, LastName); } }
}
and
<ComboBox TextSearch.TextPath="FullName" ItemsSource="collectionOfPersons"/>
Altenatively, if you don't want to touch Person, you can create a wrapper class that exposes these properties.
Best Answer
The DataContext of the controls in the DataTemplate is not inherited from it's parent. So in your case, everything in the
Templat
will have a different DataContext than CustomItem and MyControl.The DataContext for the DataTemplate comes from the Content property of the associated ContentControl or ContentPresenter. So in your case, if you did this:
Then you could set the DataContext of MyControl, and it would get passed down to your DataTemplate.
From the looks of it though, your MyControl should be an ItemsControl though (as explained here).