Access ComboBoxItem DisplayValue - wpf

I have a comboBox that has an ItemsSource of a list of objects. So the DisplayMemberPath is set to a particular property of the object. Of course this means that the correct value is displayed in the ComboBoxItem.
My issue is that I would like to be able to get that "Value" that is returned by the DisplayMemberPath in XAML so that I can bind it to something else. i.e. I would like to have a "DisplayText" property on the ComboBoxItem.
Of course I don't have this, so, does anyone know of a way to get this value without traversing down into the template of the ComboBoxItem looking for the ContentHost?
If you're interested in my specific use of this, I'm trying to do this on the style of the ComboBox:
....
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style>
<Setter
Property="AutomationProperties.AutomationId"
Value="{Binding RelativeSource={RelativeSource Self}, Path=MagicPathForDisplayedText}"/>
....
Of course Path=Content works just fine if you're just binding your ItemsSource to properties, but when it's an Object with a DisplayMemberPath, Content will be that Object.
Thanks for any help or re-framing of the problem.

The easiest way to handle problems like this is usually Attached Properties and Behaviors.
You could create two attached properties called DisplayMemberPath and DisplayText, then you bind DisplayMemberPath to the parent ComboBox DisplayMemberPath and in the PropertyChangedCallback you set up a binding of your own with the same path for DisplayText. After that you have a property which you can bind to
<Style x:Key="ComboBoxStyle" TargetType="ComboBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ComboBoxItem">
<Setter Property="behaviors:DisplayTextBehavior.DisplayMemberPath"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBox}},
Path=DisplayMemberPath}"/>
<Setter Property="AutomationProperties.AutomationId"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(behaviors:DisplayTextBehavior.DisplayText)}"/>
</Style>
</Setter.Value>
</Setter>
</Style>
DisplayTextBehavior
public class DisplayTextBehavior
{
public static DependencyProperty DisplayMemberPathProperty =
DependencyProperty.RegisterAttached("DisplayMemberPath",
typeof(string),
typeof(DisplayTextBehavior),
new FrameworkPropertyMetadata("", DisplayMemberPathChanged));
public static string GetDisplayMemberPath(DependencyObject obj)
{
return (string)obj.GetValue(DisplayMemberPathProperty);
}
public static void SetDisplayMemberPath(DependencyObject obj, string value)
{
obj.SetValue(DisplayMemberPathProperty, value);
}
private static void DisplayMemberPathChanged(object sender, DependencyPropertyChangedEventArgs e)
{
ComboBoxItem comboBoxItem = sender as ComboBoxItem;
string displayMemberPath = GetDisplayMemberPath(comboBoxItem);
comboBoxItem.SetBinding(DisplayTextProperty, new Binding(displayMemberPath));
}
public static DependencyProperty DisplayTextProperty =
DependencyProperty.RegisterAttached("DisplayText",
typeof(string),
typeof(DisplayTextBehavior),
new FrameworkPropertyMetadata(""));
public static string GetDisplayText(DependencyObject obj)
{
return (string)obj.GetValue(DisplayTextProperty);
}
public static void SetDisplayText(DependencyObject obj, string value)
{
obj.SetValue(DisplayTextProperty, value);
}
}

You could bind an intermediate Object in the ViewModel to the SelectedItem property on the Combobox. Then also Bind your other display item to that intermediate object. Then when the PropertyChanged event is fired by selecting an item, the display will also update via the event chain.

Are you using SelectedValuePath? If not you could could set it the same as DisplayMemberPath and then the selected value is available as SelectedValue.

Related

MVVM WPF Windows app - Binding to custom property in template

I'm having a binding problem, and I'm starting to think that there's something wrong with my approach to this problem.
I'm inside a Button style template, and I need to bind a DataTrigger to a custom property "BindingRef".
This code should change an Image named btnImage to "DisabledImage" when the custom property changes value.
Here's the code in the template:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(helper:BindingHelper.BindingRef), UpdateSourceTrigger=PropertyChanged}" Value="{x:Static helper:StatusEnum.Disabled}">
<Setter TargetName="btnImage" Property="Source" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Button}, Path=(helper:ImageLoader.DisabledImage)}" />
</DataTrigger>
I know, a lot of things happening there.
However everything works if instead of "(helper:BindingHelper.BindingRef)" I set a fixed binding source.
Here's BindingHelper:
public static class BindingHelper
{
public static string GetBindingRef(DependencyObject target)
{
return (string)target.GetValue(BindingRefProperty);
}
public static void SetBindingRef(DependencyObject target, string value)
{
target.SetValue(BindingRefProperty,value);
}
public static readonly DependencyProperty BindingRefProperty =
DependencyProperty.RegisterAttached("BindingRef",
typeof(string),
typeof(BindingHelper),
new PropertyMetadata(null));
}
and inside the View:
<Button ...
helper:ImageLoader.DisabledImage="/Resources/disabled.png"
Style="{StaticResource btnStyle}"
Command="{Binding btnCommand}"
helper:BindingHelper.BindingRef="MyProperty" />
This compiles and I get no errors, but it's not working.
Any idea?
Thanks!

WPF: Keeping track of relative item positions in ItemsControl/ListBox

Please see the following code.
It creates a ListBox with five items. The selected item of the ListBox is colored in yellow, previous items (index below selected index) are colored in green and future items (index above selected index) are colored in red.
ItemViewModel.vb
Public Class ItemViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private _title As String
Private _isOld As Boolean
Private _isNew As Boolean
Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
If String.IsNullOrEmpty(propertyName) Then
Exit Sub
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Public Property Title As String
Get
Return _title
End Get
Set(value As String)
_title = value
Me.OnPropertyChanged()
End Set
End Property
Public Property IsOld As Boolean
Get
Return _isOld
End Get
Set(value As Boolean)
_isOld = value
Me.OnPropertyChanged()
End Set
End Property
Public Property IsNew As Boolean
Get
Return _isNew
End Get
Set(value As Boolean)
_isNew = value
Me.OnPropertyChanged()
End Set
End Property
End Class
MainViewModel:
Public Class MainViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Private ReadOnly _items As ObservableCollection(Of ItemViewModel)
Private _selectedIndex As Integer
Public Sub New()
_items = New ObservableCollection(Of ItemViewModel)
_items.Add(New ItemViewModel With {.Title = "Very old"})
_items.Add(New ItemViewModel With {.Title = "Old"})
_items.Add(New ItemViewModel With {.Title = "Current"})
_items.Add(New ItemViewModel With {.Title = "New"})
_items.Add(New ItemViewModel With {.Title = "Very new"})
Me.SelectedIndex = 0
End Sub
Protected Overridable Sub OnPropertyChanged(<CallerMemberName> Optional propertyName As String = Nothing)
If String.IsNullOrEmpty(propertyName) Then
Exit Sub
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Public ReadOnly Property Items As ObservableCollection(Of ItemViewModel)
Get
Return _items
End Get
End Property
Public Property SelectedIndex As Integer
Get
Return _selectedIndex
End Get
Set(value As Integer)
_selectedIndex = value
Me.OnPropertyChanged()
For index As Integer = 0 To Me.Items.Count - 1
Me.Items(index).IsOld = (index < Me.SelectedIndex)
Me.Items(index).IsNew = (index > Me.SelectedIndex)
Next index
End Set
End Property
End Class
MainWindow.xaml
<Window x:Class="MainWindow"
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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="200">
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<ListBox ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedIndex}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsOld}" Value="True">
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding IsNew}" Value="True">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
This works like expected, but I don't like, that the ItemViewModel holds the properties IsOld and IsNew and that the MainViewModel is responsible for updating these properties. In my opinion that should be done by the ListBox, not by every view model that might be the DataContext for my ListBox.
I already tried to create two attached properties for ListBoxItem and bind to them (like I bound to IsSelected for the current item). But I couldn't figure out an event on which I update those attached properties.
Is using these attached properties the way to go? When and/or where do I update those attached properties?
I tried to attach to the ValueChanged event of the ItemsSource property of the ListBox to be able to attach to the CollectionChanged event of the underlying collection. But I failed getting the ListBoxItem for an item, since these containers are created asynchronously (so I assume). And since the ListBox uses a VirtualizingStackPanel by default, I wouldn't get a ListBoxItem for every item of my underlying collection anyway.
Please keep in mind that the collection of items I bind to is observable and can change. So the IsOld and IsNew properties have to be updated whenever the source collection itself changes, whenever the content of the source collection changes and whenever the selected index changes.
Or how else can I achieve what I like to achieve?
I didn't flag VB.net on purpose since the question doesn't have anything to do with VB.net and I'm fine with answers in C# as well.
Thank you.
One way you can achieve this is through an attached behavior. This allows you to keep the display behavior with the ListBox and away from your view-model, etc.
First, I created an enum to store the states of the items:
namespace WpfApp4
{
public enum ListBoxItemAge
{
Old,
Current,
New,
None
}
}
Next, I created an attached behavior class with two attached properties:
IsActive (bool) = Turns on the behavior for the ListBox
ItemAge (ListBoxItemAge) = Determines if an item should be displayed in Red, Yellow, Green, etc.
When IsActive is set to True on a ListBox, it will subscribe to the SelectionChanged event and will handle setting each ListBoxItems age.
Here is the code:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp4
{
public class ListBoxItemAgeBehavior
{
#region IsActive (Attached Property)
public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.RegisterAttached(
"IsActive",
typeof(bool),
typeof(ListBoxItemAgeBehavior),
new PropertyMetadata(false, OnIsActiveChanged));
public static bool GetIsActive(DependencyObject obj)
{
return (bool)obj.GetValue(IsActiveProperty);
}
public static void SetIsActive(DependencyObject obj, bool value)
{
obj.SetValue(IsActiveProperty, value);
}
private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is ListBox listBox)) return;
if ((bool) e.NewValue)
{
listBox.SelectionChanged += OnSelectionChanged;
}
else
{
listBox.SelectionChanged -= OnSelectionChanged;
}
}
private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = (ListBox) sender;
var selectedIndex = listBox.SelectedIndex;
SetItemAge(listBox.ItemContainerGenerator.ContainerFromIndex(selectedIndex), ListBoxItemAge.Current);
foreach (var item in listBox.ItemsSource)
{
var index = listBox.Items.IndexOf(item);
if (index < selectedIndex)
{
SetItemAge(listBox.ItemContainerGenerator.ContainerFromIndex(index), ListBoxItemAge.Old);
}
else if (index > selectedIndex)
{
SetItemAge(listBox.ItemContainerGenerator.ContainerFromIndex(index), ListBoxItemAge.New);
}
}
}
#endregion
#region ItemAge (Attached Property)
public static readonly DependencyProperty ItemAgeProperty =
DependencyProperty.RegisterAttached(
"ItemAge",
typeof(ListBoxItemAge),
typeof(ListBoxItemAgeBehavior),
new FrameworkPropertyMetadata(ListBoxItemAge.None));
public static ListBoxItemAge GetItemAge(DependencyObject obj)
{
return (ListBoxItemAge)obj.GetValue(ItemAgeProperty);
}
public static void SetItemAge(DependencyObject obj, ListBoxItemAge value)
{
obj.SetValue(ItemAgeProperty, value);
}
#endregion
}
}
The XAML looks something like this. This is just a simple example:
<ListBox
local:ListBoxItemAgeBehavior.IsActive="True"
ItemsSource="{Binding Data}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(local:ListBoxItemAgeBehavior.ItemAge), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="Old">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=(local:ListBoxItemAgeBehavior.ItemAge), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="Current">
<Setter Property="Foreground" Value="Yellow" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=(local:ListBoxItemAgeBehavior.ItemAge), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="New">
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I've created three DataTriggers that look for the value of the ListBoxItemAgeBehavior.ItemAge and then set the appropriate Foreground color. Since the attached property is set on the ListBoxItem, I'm doing a RelativeSource on the binding.
I hope this helps.

How to handle attached properties events?

I created an expander style that contains a checkbox in its header. The checkbox state is bound to an attached property:
<Style TargetType="{x:Type Expander}" x:Key="MyCheckboxExpander">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
(...)
<CheckBox x:Name="ExpanderHeaderChk" VerticalAlignment="Center" Margin="4,0,0,2"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(my:AP.IsChecked)}" />
(...)
I my view, inside the expander I have a stackpanel with a ComboBox.
Whenever the user checks the expander's checkbox, I wan't that the combobox gets the first item selected, on the oher hand whenever the user unchecks it, I wan't that the selecteditem of the combobox be null.
How can I accomplish this? I'm following the MVVM pattern, but since this is more a matter of the view, I'm open to code-behind suggestions.
Well, I think your design is not optimal. You see, you are trying to change the semantics of the Expander. The real expander doesn't have the semantics with additional checkbox, so the control you are creating is not an Expander any more.
I would suggest that you switch to a user control (or maybe a custom control, look at your semantics), and expose the needed event in your control's class. The XAML for the user control should be perhaps an expander with a checkbox.
Edit: example with UserControl (not tested)
(XAML)
<UserControl x:Class="namespace:MyCheckboxExpander">
<Expander>
...
<Checkbox x:Name="cb"/>
...
</Expander>
</UserControl>
(code-behind)
public class MyCheckboxExpander : UserControl
{
MyCheckboxExpander()
{
InitializeComponent();
cb.Check += OnCheck;
}
void OnCheck(object sender, whatever2 args)
{
if (CheckboxTriggered != null)
CheckboxTriggered(new EventArgs<whatever>);
}
public event EventArgs<whatever> CheckboxTriggered;
}
WPF is so powerfull framework, that you can solve you problem just using next style for Expander:
<Style x:Key="myExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<StackPanel>
<CheckBox x:Name="PART_CheckBox" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
<ComboBox x:Name="PART_ComboBox" ItemsSource="{TemplateBinding Content}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="PART_ComboBox" Property="SelectedIndex" Value="0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
SAMPLE:
<Expander Style="{StaticResource myExpanderStyle}">
<x:Array Type="sys:String">
<sys:String>1</sys:String>
<sys:String>2</sys:String>
<sys:String>3</sys:String>
</x:Array>
</Expander>
Just XAML! I like XAML declarativity.
But from MVVM perspective, this approach has one disadvantage - I can't cover this case with unit tests. So, I would prefer:
create view model with properties: IsChecked(bound to CheckBox),
SelectedItem(bound to ComboBox) and Source(ItemsSource for ComboBox) -
abstration of my real view without any references on controls;
write a logic in view model that set or unset SelectedItem depending
on IsChecked property;
cover that logic with unit test (yep, you can
even start with this point, if you like test first approach).
I followed the suggestion provided by #Baboon and I created a custom control with a routed event named CheckedChanged, this way I can access it through the view's xaml and code-behind:
[TemplatePart(Name = "PART_Expander", Type = typeof(Expander))]
[TemplatePart(Name = "PART_CheckBox", Type = typeof(CheckBox))]
public class MyCustomExpander : Expander
{
static MyCustomExpander()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomExpander), new FrameworkPropertyMetadata(typeof(MyCustomExpander)));
}
public bool IsChecked
{
get { return (bool)GetValue(IsCheckedProperty); }
set { SetValue(IsCheckedProperty, value); }
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register("IsChecked", typeof(bool), typeof(MyCustomExpander),
new UIPropertyMetadata(false));
#region Events
private CheckBox chkExpander = new CheckBox();
public CheckBox ChkExpander { get { return chkExpander; } private set { chkExpander = value; } }
public static readonly RoutedEvent CheckedChangedEvent = EventManager.RegisterRoutedEvent("ExtraButtonClick",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MyCustomExpander));
public event RoutedEventHandler CheckedChanged
{
add { AddHandler(CheckedChangedEvent, value); }
remove { RemoveHandler(CheckedChangedEvent, value); }
}
void OnCheckedChanged(object sender, RoutedEventArgs e)
{
RaiseEvent(new RoutedEventArgs(CheckedChangedEvent, this));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
CheckBox chk = base.GetTemplateChild("PART_CheckBox") as CheckBox;
if (chk != null)
{
chk.Checked += new RoutedEventHandler(OnCheckedChanged);
chk.Unchecked += new RoutedEventHandler(OnCheckedChanged);
}
}
#endregion
}
I want to thank to #Baboon and #Vlad for their help.

How to change font color of items in listbox (wpf)

I have a listbox which is bounded to an observable collection. The elements in the collection contain a variable called color. My listbox's items are already bounded to the collection, but how do I also bind the items font color to that? I already have a data template which works fine replacing item's name with the color name like this
<DataTemplate x:Key="myListBox">
<TextBlock Padding="0,0,10,0"
Text="{Binding Path=Color, Mode=Default}"/>
</DataTemplate>
but I can't seem to find which property I have to set in order to bind the color.
Not sure which colour you're referring to, but this will set the background and text/foreground colours.
<TextBlock Padding="0,0,10,0"
Text="{Binding Path=Color, Mode=Default}"
Background="{Binding myBackgroundColour}"
Foreground="{Binding myTextColour}"
/>
EDIT: dependancy prop -
public string Color
{
get { return (string)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
// Using a DependencyProperty as the backing store for Color. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColorProperty =
DependencyProperty.Register("Color", typeof(string), typeof(CLASSNAMEHERE), new UIPropertyMetadata("Black"));
Replace CLASSNAMEHERE with the name to the class you're putting it in, ie the viewmodel class or codebehind class name.
use:
this.Color = "Yellow";
you can use this resource style
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Foreground" Value="></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
bla bla bla
</Style>

Making the style's binding more flexible

I'm trying to make the existing style more flexible.
I'm attaching a dep. property to the double click event of the data grid row control.
On double-clicking the row i want a certain window to open.
To achieve this I've implemented a dep. property and added a style definition.
Below is the part from the view file:
<Style x:Key="SomeKey" TargetType={x:Type DataGridRow} BasedOn= "SomeOtherKey">
<Setter Property="vm:DataGridBehavior:OnDoubleClick" Value="{Binding Path=CommandName,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
</Setter>
</Style>
the attached property hooks to the double-click event on the data row
and executes the relay command bound to the view.
I'd like to enable more flexibility in the style
by specifying the command-to-be-invoked name in the view itself (as it may differ between different views).
How can I achieve that?
Is there any template definition that I'm missing?
Any help would be greatly appreciated :)
You could subclass DataGrid and add a Property for the Command, e.g MyCommand. Then you could bind that ICommand in each DataGrid and use MyCommand as Path in the RowStyle Binding
DataGrids
<local:CommandDataGrid RowStyle="{StaticResource SomeKey}"
MyCommand="{Binding CommandName1}">
<!-- ... -->
<local:CommandDataGrid RowStyle="{StaticResource SomeKey}"
MyCommand="{Binding CommandName2}">
RowStyle
<Style x:Key="SomeKey" TargetType="{x:Type DataGridRow}">
<Setter Property="vm:DataGridBehavior.OnDoubleClick"
Value="{Binding Path=MyCommand,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
</Style>
CommandDataGrid
public class CommandDataGrid : DataGrid
{
public static readonly DependencyProperty MyCommandProperty =
DependencyProperty.Register("MyCommand",
typeof(ICommand),
typeof(CommandDataGrid),
new UIPropertyMetadata(null));
public ICommand MyCommand
{
get { return (ICommand)GetValue(MyCommandProperty); }
set { SetValue(MyCommandProperty, value); }
}
}
Alternatively, you could create an attached property e.g MyCommand that you use
DataGrid
<DataGrid vm:DataGridBehavior.MyCommand="{Binding CommandName}"
RowStyle
<Style x:Key="SomeKey" TargetType="{x:Type DataGridRow}">
<Setter Property="vm:DataGridBehavior.OnDoubleClick"
Value="{Binding Path=(vm:DataGridBehavior.MyCommand),
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
</Style>
MyCommandProperty
public static readonly DependencyProperty MyCommandProperty =
DependencyProperty.RegisterAttached("MyCommand",
typeof(ICommand),
typeof(DataGridBehavior),
new UIPropertyMetadata(null));
public static void SetMyCommand(DependencyObject element, ICommand value)
{
element.SetValue(MyCommandProperty, value);
}
public static ICommand GetMyCommand(DependencyObject element)
{
return (ICommand)element.GetValue(MyCommandProperty);
}

Resources