In my previous blog on DependencyProperty, I talked about how to create properties in objects using DependencyProperty and DependencyObject, to have support for Databinding, defaults, expressions, events and validations.
But on some occasions, you want to assign a parent object needs to assign a property to the children objects, regardless of the type of object.
Traditionally, this has been done using base class and inheritance. For example, if you wanted to create a panel control that understands commands, you would need to create a base class 'CmdControl" something like this:
public
partial
class
CmdControl : UserControl
{
public CmdControl()
{
InitializeComponent();
}
private
string _cmd;
public
string Cmd
{
get
{
return _cmd;
}
set
{
_cmd = value;
}
}
}
Then you would create all your controls derived from CmdControl, thus ensuring that each control has a Cmd property:
public
partial
class
MyControl : CmdControl
{
public MyControl()
{
this.Cmd = "Do this";
InitializeComponent();
}
}
But this method did not allow the use of existing controls or classes.
With attached properties, a property can be set for each child control but the storage of the value is handled by the parent class.
Let's see how to declare the Grid control and the Cmd attached property:
public
partial
class
MyPanel : System.Windows.Controls.Grid
{
public MyPanel()
{
InitializeComponent();
}
public
static
string GetCmd(DependencyObject obj)
{
return (string)obj.GetValue(CmdProperty);
}
public
static
void SetCmd(DependencyObject obj, string value)
{
obj.SetValue(CmdProperty, value);
}
public
static
readonly DependencyProperty CmdProperty =
DependencyProperty.RegisterAttached("Cmd", typeof(string), typeof(MyPanel), new UIPropertyMetadata("Open"));
}
In XAML, the panel is used as per my previous blog:
<Window
x:Class="WPF2.Window1"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
xmlns:AppCode="clr-namespace:WPF2"
Title="WPF2"
Height="263"
Width="239"
>
<AppCode:MyPanel
x:Name="Panel1">
<Button
Name="Button1"
Height="23"
Margin="50,0,50,0" >Button1</Button>
<Button
Name="Button2"
Height="23"
Margin="50,50,50,0" >Button2</Button>
</AppCode:MyPanel>
</Window>
You can then programmatically assign a command value to any child control:
public
partial
class
Window1 : System.Windows.Window
{
public Window1()
{
InitializeComponent();
MyPanel.SetCmd(Button1, "Open 1");
MyPanel.SetCmd(Button2, "Close 1");
Button1.Click += new
RoutedEventHandler(Button_Click);
Button2.Click += new
RoutedEventHandler(Button_Click);
}
void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("My Command is " + MyPanel.GetCmd(sender as
DependencyObject));
}
}
Or you can do the same thing in XAML:
<Window
x:Class="WPF2.Window1"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
xmlns:AppCode="clr-namespace:WPF2"
Title="WPF2"
Height="263"
Width="239"
>
<AppCode:MyPanel
x:Name="Panel1">
<Button
AppCode:MyPanel.Cmd="Open 1"
Click="Button_Click"
Height="23"
Margin="50,0,50,0" >Button1</Button>
<Button
AppCode:MyPanel.Cmd="Close 1"
Click="Button_Click"
Height="23"
Margin="50,50,50,0" >Button2</Button>
</AppCode:MyPanel>
</Window>
When you launch the application, and you click on either button, you get a message box with the text of the command assigned to that button.
More information on attached properties can be found here.
0 comments:
Post a Comment