We have many TextBlocks in our application and many of them must have ToolTips.
Often the ToolTip should display the same as the TextBlock.Text property.
Also the ToolTip should not be displayed if the TextBlock.Text = "" or null.
So we have this solution in many many places:
<TextBlock Text="{Binding SomeTextProperty}">
<TextBlock.ToolTip>
<ToolTip Visibility="{Binding SomeTextProperty}, Converter={StaticResource StringToVisibilityConverter}">
<TextBlock Text="{Binding SomeTextProperty}" />
</TextBlock.ToolTip>
</TextBlock>
Notice:
I have to specify the SomeTextProperty three times on each TextBlock that need a TooLTip with this functionality.This seems very redundant!
The ToolTip.Content is a TextBlock itself.This is because I need to have a Style on the TextBlock.I have omitted that style to keep this post as simple as possible.
So I have tried to invent a Style for TextBlocks that use Bindings with RelativeSource to get the TextBlock.Text property for the ToolTip. I came up with this solution:
MainWindow (Just copy-paste more or less)
<Window x:Class="Main.Views.ToolTips"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Main.Views"
xmlns:converters="clr-namespace:Main.Converters"
mc:Ignorable="d"
Title="ToolTips" Height="450" Width="800">
<Window.Resources>
<Style TargetType="TextBlock" x:Key="TextBlockWithToolTipStyle">
<Style.Resources>
<converters:StringToVisibilityConverter x:Key="StringToVisibilityConverter" />
</Style.Resources>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Visibility="{Binding Text, RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}, Converter={StaticResource StringToVisibilityConverter}}">
<ToolTip.Content>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}}" />
</ToolTip.Content>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="This should display a tooltip" />
<TextBlock Text="asdf"
Background="Gray"
Style="{StaticResource TextBlockWithToolTipStyle}" />
<Separator Height="50" Visibility="Hidden" />
<TextBlock Text="This should not display a tooltip" />
<TextBlock Text=""
Background="LightGray"
Style="{StaticResource TextBlockWithToolTipStyle}" />
</StackPanel>
</Window>
StringToVisibilityConverter
public class StringToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var input = value is null ? string.Empty : value.ToString();
return string.IsNullOrWhiteSpace(input) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
This, of course, don't work!
I put a breakpoint in the StringToVisibilityConverter and that breakpoint is not hit when I hover both TextBlocks in the Window.
In VS's XAML Binding Failures view I see two binding errors that regards ToolTip.Visibility and TextBlock.Text:
ToolTip.Visibility: Cannot find source: RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TextBlock', AncestorLevel='1'
TextBlock.Text: Cannot find source: RelativeSource FindAncestor, AncestorType='System.Windows.Controls.TextBlock', AncestorLevel='1'
Is this possible to solve?
If so, how?
/BR,
Steffe
The ToolTip is not part of the visual tree. That's why your Binding.RelativeSource does not resolve.
To reference the element that is decorated by the ToolTip you must reference the ToolTip.PlacementTarget property:
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ToolTip}, Path=PlacementTarget.Text}" />
Furthermore, you should not try to toggle the ToolTip.Visibility. It won't work.
Instead use a Trigger to set the ToolTip.
The correct solution would be as followed:
<Style TargetType="TextBlock"
x:Key="TextBlockWithToolTipStyle">
<Style.Resources>
<ToolTip x:Key="ToolTip">
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=ToolTip}, Path=PlacementTarget.Text}" />
</ToolTip>
</Style.Resources>
<Setter Property="ToolTip"
Value="{StaticResource ToolTip}" />
<Style.Triggers>
<Trigger Property="Text" Value="">
<Setter Property="ToolTip" Value="{x:Null}" />
</Trigger>
</Style.Triggers>
</Style>
I have created different controls in WPF with their respective control templates in which styling is almost similar but binding is different, as given below removing extra clutter. I am looking for a way to make a common ControlTemplate with some way to make the binding dynamic.
ControlTemplate for MasterRuleLayout control
<ControlTemplate TargetType="{x:Type local:MasterRuleLayout}">
<StackPanel>
<Image
Style="{StaticResource MasterLayoutImageStyle}"
DataContext="{Binding CommonAggregate.SelectedRule}">
</Image>
<TextBox
Text="{Binding CommonAggregate.SelectedRule.Name}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding CommonAggregate.SelectedRule.Parent}"
Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</ControlTemplate>
ControlTemplate for MasterEntityLayout control
<ControlTemplate TargetType="{x:Type local:MasterEntityLayout}">
<StackPanel>
<Image
Style="{StaticResource MasterLayoutImageStyle}"
DataContext="{Binding CommonAggregate.SelectedEntityItem}">
</Image>
<TextBox
Text="{Binding CommonAggregate.SelectedEntityItem.Name}">
</TextBox>
</StackPanel>
</ControlTemplate>
Bindings need dependency properties to form the "glue" between the properties in your template bindings and the properties in the view models that you're binding to. That means your options are 1) use TemplateBinding to bind via existing properties in the templated parent, 2) create a custom control with any additional properties that are missing, or 3) use attached properties:
<Window.Resources>
<ControlTemplate x:Key="MyTemplate" TargetType="{x:Type Control}">
<TextBlock Text="{Binding Path=(local:AttachedProps.Name), Mode=OneWay,
RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
</Window.Resources>
<Control Template="{StaticResource MyTemplate}"
local:AttachedProps.Name="{Binding MyViewModelName, Mode=OneWay}" />
And then you would create the attached property itself like so:
public static class AttachedProps
{
#region Name
public static string GetName(DependencyObject obj)
{
return (string)obj.GetValue(NameProperty);
}
public static void SetName(DependencyObject obj, string value)
{
obj.SetValue(NameProperty, value);
}
public static readonly DependencyProperty NameProperty =
DependencyProperty.RegisterAttached("Name", typeof(string),
typeof(AttachedProps), new PropertyMetadata(String.Empty));
#endregion Name
}
I have a DataGrid that looks something like this.
I have grouped data by Gender. My GroupItem style is
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp" IsExpanded="True"
Background="White"
Foreground="Black">
<Expander.Header>
<TextBlock Text="{Binding Name}"/>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I want my Group Header 'Male' and 'Female' to look like 'Gender : Male' and 'Gender : Female' instead of simple plain 'Male' and 'Female'. How can I modify my GroupItem style to achieve this so that every time I group my data in datagrid the group header can appear like GroupHeaderTitle : GroupHeaderValue? or Do I need to change anything other than GroupItem style to achieve this?
You can add a property GroupTitle which represents the desired group title at your view model if you are using MVVM or to your Window code-behind otherwise, then add another TextBlock at the Expander.Header which is bound to the GroupTitle property, see the following code snippet:
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="exp" IsExpanded="True"
Background="White" Foreground="Black">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=DataContext.GroupTitle}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When you add the grouping just supply a converter:
// Get the default view
ICollectionView view = CollectionViewSource.GetDefaultView(...);
// Do the grouping
view.GroupDescriptions.Clear();
view.GroupDescriptions.Add(new PropertyGroupDescription("Gender", new GenderConverter()));
// The converter
public class GenderConverter : IValueConverter
{
public object Convert(object value,
Type targetType, object parameter, CultureInfo culture)
{
return string.Format("Gender: {0}", value);
}
public object ConvertBack(object value,
Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
I am wondering if it was possible to change the styling of a column in a wpf datagrid depending on the type of item in the ItemsSource collection.
I have a wpf datagrid from the wpf toolkit. The single rows in the grid should be styled depending of the type of item from the ItemsSource collection. So all items are of the same base class type but the columns of some derived types should get a different stylization.
Is this possible?
Thank you :-)
A WPF-only solution:
I am a little late for the party but if someone else is trying to do something like this, there is a WPF only solution. There are no DataGridColumn class that will directly look for the proper DataTemplate but we can indirectly use a ContentPresenter like this:
<Window.Resources>
<DataTemplate DataType="{x:Type models:Employee}">
<Grid>...</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type models:Manager}">
<Grid>...</Grid>
</DataTemplate>
</Window.Resources>
<DataGrid ... >
<DataGrid.Columns>
<DataGridTemplateColumn Header="MyColumn">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
By sandwiching a ContentPresenter inside a DataTemplate inside the CellTemplate, we achieve the desired result.
Yes, it is possible to do it in several ways. The one I would go for is writing your own custom "typeswitch" converter that selects a value depending on type of input. Like this:
public class TypeSwitchConverter : Dictionary<Type, object>, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, .CultureInfo culture)
{
foreach (var mapping in this)
{
if (mapping.Key.IsAssignableFrom(value.GetType()))
{
return mapping.Value;
}
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
And then use a binding for the Style of the top-level element in template for your cell, and use the above converter for that binding as needed. Here's a simplified example that styles items in a ListBox using it:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.Style>
<Binding>
<Binding.Converter>
<my:TypeSwitchConverter>
<Style x:Key="{x:Type cor:Int32}" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="Red" />
</Style>
<Style x:Key="{x:Type cor:String}" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="Green" />
</Style>
<Style x:Key="{x:Type sys:Uri}" TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="Blue" />
</Style>
</my:TypeSwitchConverter>
</Binding.Converter>
</Binding>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have a list of options in a data object, and I want to make the equivalent of a radio button list to allow the user to select one and only one of them. Functionality similar to a databound combo box, but in radio button format.
Silly me, I thought this would be built in, but no. How do you do it?
Basically, after reviewing the google results, I started with the info from an MSDN discussion thread where Dr. WPF provided an answer, which talks about styling a ListBox to look right. However, when the listbox is disabled, the background was an annoying color that I couldn't get rid of for the life of me, until I read the MSDN example of the ListBox ControlTemplate, which shows the secret Border element that was kicking my background butt.
So, the final answer here was this style:
<Style x:Key="RadioButtonList" TargetType="{x:Type ListBox}">
<!-- ControlTemplate taken from MSDN http://msdn.microsoft.com/en-us/library/ms754242.aspx -->
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="95"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border Name="Border" Background="Transparent"
BorderBrush="Transparent"
BorderThickness="0"
CornerRadius="2">
<ScrollViewer Margin="0" Focusable="false">
<StackPanel Margin="2" IsItemsHost="True" />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Border" Property="Background"
Value="Transparent" />
<Setter TargetName="Border" Property="BorderBrush"
Value="Transparent" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="theBorder" Background="Transparent">
<RadioButton Focusable="False" IsHitTestVisible="False"
IsChecked="{TemplateBinding IsSelected}">
<ContentPresenter />
</RadioButton>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
Which provides a ControlTemplate for, and styles, the ListBox and the Items. And it gets used like this:
<ListBox Grid.Column="1" Grid.Row="0" x:Name="TurnChargeBasedOnSelector" Background="Transparent"
IsEnabled="{Binding Path=IsEditing}"
Style="{StaticResource RadioButtonList}"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainForm}}, Path=DataContext.RampTurnsBasedOnList}"
DisplayMemberPath="Description" SelectedValuePath="RampTurnsBasedOnID"
SelectedValue="{Binding Path=RampTurnsBasedOnID, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"/>
The more I spend time with WPF, the more I think it makes the trivial insanely difficult and the insanely difficult trivial. Enjoy. -Scott
Super Simple, MVVM friendly, leveraging DataTemplates for types.
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:Option}">
<RadioButton Focusable="False"
IsHitTestVisible="False"
Content="{Binding Display}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}">
</RadioButton>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Options}" SelectedItem="{Binding SelectedOption}"/>
</Grid>
View Model, etc:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new Vm();
}
}
public class Vm
{
public Option[] Options { get { return new Option[] {
new Option() { Display = "A" },
new Option() { Display = "B" },
new Option() { Display = "C" } }; } }
public Option SelectedOption { get; set; }
}
public class Option
{
public string Display { get; set; }
}
If you wrap your option into a specific type (or likely it is already). You can just set a DataTemplate for that type, WPF will automatically use it. (Define DataTemplate in ListBox resources to limit the scope of where the DataTemplate will be applied).
Also use group name in the DataTemplate to set the group if you want.
This is much simpler than changing the control template, however it does mean that you get a blue line on selected items. (Again, nothing a bit of styling can't fix).
WPF is simple when you know how.
Bind the listbox to the ItemsSource of a ListBox with a list of objects that have a property Name (this can change)
<ListBox Name="RadioButtonList">
<ListBox.ItemTemplate >
<DataTemplate >
<RadioButton GroupName="radioList" Tag="{Binding}" Content="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
important GroupName="radioList"
I've done this through a ValueConverter that converts an enum to a bool. By passing the enum value that your radio button represents as the ConverterParameter, the converter returns whether this radio button should be checked or not.
<Window.Resources>
<Converters:EnumConverter x:Key="EnumConverter" />
</Window.Resources>
<RadioButton IsChecked="{Binding Path=MyEnum, Mode=TwoWay,
Converter={StaticResource EnumConverter},
ConverterParameter=Enum1}"}
Content="Enum 1" />
<RadioButton IsChecked="{Binding Path=MyEnum, Mode=TwoWay,
Converter={StaticResource EnumConverter},
ConverterParameter=Enum2}"}
Content="Enum 2" />
EnumConverter is defined as follows:
public class EnumConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType.IsAssignableFrom(typeof(Boolean)) && targetType.IsAssignableFrom(typeof(String)))
throw new ArgumentException("EnumConverter can only convert to boolean or string.");
if (targetType == typeof(String))
return value.ToString();
return String.Compare(value.ToString(), (String)parameter, StringComparison.InvariantCultureIgnoreCase) == 0;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType.IsAssignableFrom(typeof(Boolean)) && targetType.IsAssignableFrom(typeof(String)))
throw new ArgumentException("EnumConverter can only convert back value from a string or a boolean.");
if (!targetType.IsEnum)
throw new ArgumentException("EnumConverter can only convert value to an Enum Type.");
if (value.GetType() == typeof(String))
{
return Enum.Parse(targetType, (String)value, true);
}
//We have a boolean, as for binding to a checkbox. we use parameter
if ((Boolean)value)
return Enum.Parse(targetType, (String)parameter, true);
return null;
}
}
Note that I don't databind to the list of enums to generate the radio buttons, I've done them by hand. If you wanted to fill the list of radio buttons through a binding, I think you'll need to change the IsChecked binding to a MultiBinding which binds to both the current value and the radio's enum value, because you cannot use a binding on ConverterParameter.
Sorry, I'd like to put this response to Scott O's post as a comment on his post, but I do not yet have the reputation to do that. I really liked his answer as it was a style-only solution and hence didn't require any added code-behind or creating a custom-control, etc.
However, I did have one issue when I then went to try using controls inside the ListBoxItems. When I use this style I am unable to focus any of the contained controls due to this line:
<RadioButton Focusable="False"
IsHitTestVisible="False"
IsChecked="{TemplateBinding IsSelected}">
The radio button needs to turn off Focusable and IsHitTestVisible for the IsChecked binding to work correctly. To get around this, I changed the IsChecked from a TemplateBinding to a regular binding, which allowed me to make it a two-way binding. Removing the offending settings gave me this line:
<RadioButton IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsSelected, Mode=TwoWay}">
Which now allows me to focus any controls contained in ListBoxItems as expected.
Hope this helps.
I took my inspiration from Jon Benson's blog entry, but modified his solution to use enumerations that have a description attribute. So the key parts of the solution became:
Enumerator with descriptions
public enum AgeRange {
[Description("0 - 18 years")]
Youth,
[Description("18 - 65 years")]
Adult,
[Description("65+ years")]
Senior,
}
Code for reading descriptions and returning key/value pairs for binding.
public static class EnumHelper
{
public static string ToDescriptionString(this Enum val)
{
var attribute =
(DescriptionAttribute)
val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false).
SingleOrDefault();
return attribute == default(DescriptionAttribute) ? val.ToString() : attribute.Description;
}
public static List<KeyValuePair<string,string>> GetEnumValueDescriptionPairs(Type enumType)
{
return Enum.GetValues(enumType)
.Cast<Enum>()
.Select(e => new KeyValuePair<string, string>(e.ToString(), e.ToDescriptionString()))
.ToList();
}
}
Your Object Data Provider in XAML
<ObjectDataProvider
ObjectType="{x:Type local:EnumHelper}"
MethodName="GetEnumValueDescriptionPairs"
x:Key="AgeRanges">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:AgeRange" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
Your ListBox in XAML
<ListBox
ItemsSource="{Binding Source={StaticResource AgeRanges}}"
SelectedValue="{Binding SelectedAgeRange}"
SelectedValuePath="Key">
<ListBox.ItemTemplate>
<DataTemplate>
<RadioButton
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Content="{Binding Value}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The property (e.g. in your view model) that you are binding to
public class YourViewModel : INotifyPropertyChanged
{
private AgeRange _selectedAgeRange;
public AgeRange SelectedAgeRange
{
get { return _selectedAgeRange; }
set
{
if (value != _selectedAgeRange)
{
_selectedAgeRange = value;
OnPropertyChanged("SelectedAgeRange");
}
}
}
}
I cheated:
My solution was to bind the list box programaticly since that is all that seemed to work for me:
if (mUdData.Telephony.PhoneLst != null)
{
lbPhone.ItemsSource = mUdData.Telephony.PhoneLst;
lbPhone.SelectedValuePath = "ID";
lbPhone.SelectedValue = mUdData.Telephony.PrimaryFaxID;
}
The XAML looks like this:
<ListBox.ItemTemplate >
<DataTemplate >
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<RadioButton
IsChecked="{Binding Path=PrimaryPhoneID}"
GroupName="Phone"
x:Name="rbPhone"
Content="{Binding Path=PrimaryPhoneID}"
Checked="rbPhone_Checked"/>
<CheckBox Grid.Column="2" IsEnabled="False" IsChecked="{Binding Path=Active}" Content="{Binding Path=Number}" ></CheckBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
And in my event to read the value of the radio button as it is selected looks like this:
private void rbPhone_Checked(object sender, RoutedEventArgs e)
{
DataRowView dvFromControl = null;
dvFromControl = (DataRowView)((RadioButton)sender).DataContext;
BindData.Telephony.PrimaryPhoneID = (int)dvFromControl["ID"];
}
Hope that helps someone.