I have created Attached Property, for learning purposes but can't get successful result.
public class AQDatagridDependencyProperties: DependencyObject
{
public static void SetCustomDataSource(AQDataGrid element, string value)
{
element.SetValue(CustomDataSourceProperty, value);
}
public static string GetCustomDataSource(AQDataGrid element)
{
return (string)element.GetValue(CustomDataSourceProperty);
}
// Using a DependencyProperty as the backing store for DataSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CustomDataSourceProperty =
DependencyProperty.Register("CustomDataSource", typeof(string), typeof(AQDataGrid), new PropertyMetadata("obuolys"));
}
I've placed this attached property in my custom datagrid User Control which is implemented in UserView Page.
<Page x:Class="PDB.UsersView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PDB"
xmlns:PDB ="clr-namespace:PDBapi;assembly=PDBapi"
xmlns:Wpf ="clr-namespace:AQWpf;assembly=AQWpf"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Users"
Name="Users"
VisualBitmapScalingMode="LowQuality"
>
<Page.DataContext>
<PDB:UsersViewModel x:Name="vm"/>
</Page.DataContext>
<Grid VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling">
<Wpf:AQDataGrid DataContext="{Binding AQDatagridViewModel}" Wpf:AQDatagridDependencyProperties.CustomDataSource="Something" />
</Grid>
Question is how to bind that attached property value inside Custom Datagrid User Control? Example:
<UserControl x:Class="AQWpf.AQDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:AQWpf"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
Name="AQCustomDataGrid"
>
<!--Custom Data grid Implementation-->
<DataGrid x:Name="InstructionsDataGrid"
Grid.Row="1"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:AQDataGrid}, Path=DataContext}"
Style="{StaticResource OptimizedAGDatagrid}"
ItemsSource="{Binding Data}"
CurrentItem="{Binding SelectedObject, Mode=TwoWay}"
CurrentColumn="{Binding CurrentColumn, Mode=TwoWay}"
CurrentCell="{Binding CurrentCells, Mode=TwoWay}"
Tag="<----How to bind here? ---->}"
>
Your attached property declaration is incorrect. You must call RegisterAttached instead of Register, and the third argument passed to the method must by the type of the class that declares the property.
Besides that, the declaring class does not need to be derived from DependencyObject, and could even be declared static:
public static class AQDatagridDependencyProperties
{
public static readonly DependencyProperty CustomDataSourceProperty =
DependencyProperty.RegisterAttached( // here
"CustomDataSource",
typeof(string),
typeof(AQDatagridDependencyProperties), // and here
new PropertyMetadata("obuolys"));
public static string GetCustomDataSource(AQDataGrid element)
{
return (string)element.GetValue(CustomDataSourceProperty);
}
public static void SetCustomDataSource(AQDataGrid element, string value)
{
element.SetValue(CustomDataSourceProperty, value);
}
}
You would set that property like
<local:AQDataGrid local:AQDatagridDependencyProperties.CustomDataSource="something" >
and bind to it by an expression like
Tag="{Binding Path=(local:AQDatagridDependencyProperties.CustomDataSource),
RelativeSource={RelativeSource AncestorType=UserControl}}"
As a note, you would typically declare the property as a regular dependency property in the AQDataGrid class.
You were defining a simple DepencyProperty. You have to use the DependencyProperty.RegisterAttached method to register the DependencyProperty as an attached property.
Also the owner type must be set to the declaring class' type (typeof(AQDatagridDependencyProperties)) and not the attaching type (typeof(AQDataGrid)):
AQDatagridDependencyProperties.cs
public class AQDatagridDependencyProperties : DependencyObject
{
public static readonly DependencyProperty CustomDataSourceProperty = DependencyProperty.RegisterAttached(
"CustomDataSource",
typeof(string),
typeof(AQDatagridDependencyProperties),
new FrameworkPropertyMetadata("obuolys", AQDatagridDependencyProperties.DebugPropertyChanged));
private static void DebugPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var oldValue = e.OldValue; // Set breakpoints here
var newValue = e.NewValue; // in order to track property changes
}
public static void SetCustomDataSource(DependencyObject attachingElement, string value)
{
attachingElement.SetValue(CustomDataSourceProperty, value);
}
public static string GetCustomDataSource(DependencyObject attachingElement)
{
return (string) attachingElement.GetValue(CustomDataSourceProperty);
}
}
Usage
<AQDataGrid AQDatagridDependencyProperties.CustomDataSource="Something" />
Inside the AQDataGrid control:
<DataGrid x:Name="InstructionsDataGrid"
Tag="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=AQDataGrid}, Path=(AQDatagridDependencyProperties.CustomDataSource)}" />
Related
I want to create a simple wpf user control which has 2 commands, each with a single CommandParameter which is set by a DependencyProperty in the XAML.
However the value of the property bound to the CommandParameter isn't passed through to the CommandHandler. I'm using ReactiveUI to implement the Commands.
The commands are being called as expected, however the CommandParameter is always 0. So I have 2 questions:
Question 1
Even if I have a single command DependencyProperty called "Command" and a single DependencyProperty parameter called "CommandParameter", the parameter isn't passed through.
Question2
How are Command and CommandParameter properties linked together? Is it a naming convention and if so does it support multiple commands (e.g. is Command1 linked to Command1Parameter?).
I'm aware of passing multiple parameters to a single command, but this is a different scenario where I have 2 separate commands. In this case I actually want to pass the same value to both commands.
I've created a simple test app to demo the problem; The MainWindow.xaml is
<Window x:Class="WpfApp1.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="450" Width="800">
<Grid>
<StackPanel>
<local:WidgetUserControl x:Name="Widget1" Command="{Binding WidgetCommand1}"
CommandParameter="1" Command2="{Binding WidgetCommand2}" />
<local:WidgetUserControl x:Name="Widget2" Command="{Binding WidgetCommand1}"
CommandParameter="1" Command2="{Binding WidgetCommand2}"/>
</StackPanel>
</Grid>
</Window>
The MainViewModel is:
public class MainViewModel : ReactiveObject
{
public ReactiveCommand<int, Unit> WidgetCommand1 { get; }
public ReactiveCommand<int, Unit> WidgetCommand2 { get; }
public MainViewModel()
{
WidgetCommand1 = ReactiveCommand.Create<int>(ExecuteWidgetCommand1);
WidgetCommand2 = ReactiveCommand.Create<int>(ExecuteWidgetCommand2);
}
private void ExecuteWidgetCommand1(int arg)
{
MessageBox.Show($"Widget Command 1: Parameter {arg}");
}
private void ExecuteWidgetCommand2(int arg)
{
MessageBox.Show($"Widget Command 2: Parameter {arg}");
}
}
The WidgetUserControl XAML is:
<UserControl x:Class="WpfApp1.WidgetUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Border BorderBrush="Aqua" BorderThickness="2">
<StackPanel Orientation="Horizontal" Margin="5">
<Button Content="Button1"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=Command}"/>
<Button Content="Button2"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}, Path=Command2}"/>
</StackPanel>
</Border>
</Grid>
</UserControl>
The WidgetUserControl code behind looks like this:
public partial class WidgetUserControl : UserControl
{
public WidgetUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(WidgetUserControl));
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(WidgetUserControl),
new PropertyMetadata(OnCommandParameterCallback));
public static readonly DependencyProperty Command2Property = DependencyProperty.Register("Command2", typeof(ICommand), typeof(WidgetUserControl));
public static readonly DependencyProperty Command2ParameterProperty = DependencyProperty.Register("Command2Parameter", typeof(object), typeof(WidgetUserControl),
new PropertyMetadata(OnCommandParameterCallback));
public ICommand Command
{
get => (ICommand)GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
public ICommand Command2
{
get => (ICommand)GetValue(Command2Property);
set => SetValue(Command2Property, value);
}
public object Command2Parameter
{
get => GetValue(Command2ParameterProperty);
set => SetValue(Command2ParameterProperty, value);
}
private static void OnCommandParameterCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// Not sure if this is needed
var control = sender as WidgetUserControl;
control.CommandParameter = e.NewValue;
}
}
You can use the CommandParameter in the xaml binding to pass along a parameter to the command. This is available on the Button or similar controls that support Command's.
In your code, you assigned two commands to each button. When those buttons executed the command which they had assigned to, they will pass its own command parameter.Below is the source code from ButtonBase and MS.Internal.Commands.CommandHelpers that actually do the work.
protected virtual void OnClick()
{
RoutedEventArgs newEvent = new RoutedEventArgs(ButtonBase.ClickEvent, this);
RaiseEvent(newEvent);
MS.Internal.Commands.CommandHelpers.ExecuteCommandSource(this);
}
[SecurityCritical, SecurityTreatAsSafe]
internal static void ExecuteCommandSource(ICommandSource commandSource)
{
CriticalExecuteCommandSource(commandSource, false);
}
[SecurityCritical]
internal static void CriticalExecuteCommandSource(ICommandSource commandSource, bool userInitiated)
{
ICommand command = commandSource.Command;
if (command != null)
{
object parameter = commandSource.CommandParameter;
IInputElement target = commandSource.CommandTarget;
RoutedCommand routed = command as RoutedCommand;
if (routed != null)
{
if (target == null)
{
target = commandSource as IInputElement;
}
if (routed.CanExecute(parameter, target))
{
routed.ExecuteCore(parameter, target, userInitiated);
}
}
else if (command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
So basically, if you want to write a UserControl to support ICommand, you must fill your own logic like when and how to execute them. Or at least, pass the CommandParameter to the control that actually execute the command.
I am trying to make a UserControl with a ComboBox and binding to the ItemSource and SelectedItem (I also have some other controls with binding in the UserControl, but those are working fine and have been removed to simplify the code below).
The ItemSource binding seems to be working and the ComboBox is populated with the list specified in the MainWindow, but the SelectedItem is not updated on a change in either direction. Although the VersionText is updated on a change of the SelectedSoftwareVersion.Version outside of the UserControl.
I am probaly missing something basic here, but I cannot see it. I have limited experience wiht UserControls.
SoftwareTile.xaml
<UserControl x:Class="MyApp.Controls.SoftwareTile"
x:Name="softwareTile"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyApp.Controls"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="150">
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType={x:Type UserControl}, Mode=FindAncestor}}">
<StackPanel>
<TextBlock x:Name="VersionText"
Text="{Binding ElementName=softwareTile, Path=Version}"/>
<TextBlock x:Name="VersionLabel"
Text="Version"/>
<ComboBox x:Name="VersionSelect"
ItemsSource="{Binding ElementName=softwareTile, Path=VersionList}"
SelectedItem="{Binding ElementName=softwareTile, Path=VersionSelected}"/>
</StackPanel>
</Grid>
</UserControl>
SoftwareTile.cs
using System.Windows;
using System.Windows.Controls;
using System.Collections;
namespace MyApp.Controls
{
public partial class SoftwareTile : UserControl
{
public static readonly DependencyProperty VersionProperty = DependencyProperty.Register("Version", typeof(string), typeof(SoftwareTile), new PropertyMetadata(string.Empty));
public static readonly DependencyProperty VersionListProperty = DependencyProperty.Register("VersionList", typeof(IEnumerable), typeof(SoftwareTile), new UIPropertyMetadata(null));
public static readonly DependencyProperty VersionSelectedProperty = DependencyProperty.Register("VersionSelected", typeof(object), typeof(SoftwareTile), new UIPropertyMetadata(null));
public string Version
{
get { return (string)GetValue(VersionProperty); }
set { SetValue(VersionProperty, value); }
}
public IEnumerable VersionList
{
get { return (IEnumerable)GetValue(VersionListProperty); }
set { SetValue(VersionListProperty, value); }
}
public object VersionSelected
{
get { return (object)GetValue(VersionSelectedProperty); }
set { SetValue(VersionSelectedProperty, value); }
}
}
}
MainWindow.xaml
<uc:SoftwareTile x:Name="ST1"
Version="{Binding SelectedSoftwareVersion.Version}"
VersionList="{Binding SoftwareVersions.VersionList}"
VersionSelected="{Binding SelectedSoftwareVersion.Version, Mode=TwoWay}" />
using WPF, c#, VS 2012
Try to implement some custom behaviors for UI with WPF.
Currently create class that inherited from Behavior<FrameworkElement>
Idea: create one area on UI for entering name (I used textBox) - another area (Rectangle) - press and see some action with data from prev field.
What was done:
Class for implementing idea (class with Behavior)
class SayHello: Behavior<FrameworkElement>
{
public string Words { get; set; }
protected override void OnAttached()
{
AssociatedObject.MouseLeftButtonUp += OnMouseClick;
}
private void OnMouseClick(object sender,
System.Windows.Input.MouseButtonEventArgs e)
{
MessageBox.Show(string.Format("hello , {0}", Words));
}
protected override void OnDetaching()
{
AssociatedObject.MouseLeftButtonUp -= OnMouseClick;
}
}
XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:local="clr-namespace:CH08.MovingCircle"
x:Class="CH08.MovingCircle.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Canvas>
<Border Canvas.Top="220" BorderBrush="Black"
BorderThickness="2">
<TextBox x:Name="_enteredWords" Width="200"/>
</Border>
<Rectangle Stroke="Blue" Canvas.Top="250" Fill="Aquamarine"
Width="200" Height="50">
<i:Interaction.Behaviors>
<local:SayHello
Words="{Binding Text, ElementName=_enteredWords}"/>
</i:Interaction.Behaviors>
</Rectangle>
</Canvas>
Got error : A 'Binding' cannot be set on the 'Words' property of type 'SayHello'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject...
If i change part of XAML to
<Rectangle Stroke="Blue" Canvas.Top="250" Fill="Aquamarine"
Width="200" Height="50">
<i:Interaction.Behaviors>
<local:SayHello
Words="Adbracadabra"/>
</i:Interaction.Behaviors>
</Rectangle>
all works (mean just remove binding).
Question: are it's possible to create binding to properties for class with custom behavior? If yes, how can i do this?
EDIT:
As was suggested by vfabre - changed property to dependency property
public string Words
{
get { return (string)GetValue(WordsProperty); }
set { SetValue(WordsProperty, value); }
}
// Using a DependencyProperty as the backing store for Words.
//This enables animation, styling, binding, etc...
public static DependencyProperty WordsProperty =
DependencyProperty.Register("Words", typeof(string),
typeof(SayHello), new PropertyMetadata(default(string)));
Result
Maybe the error message give us the solution. You have to convert your Words property to a dependency propery the following is an example:
public string Words
{
get { return (string)GetValue(WordsProperty); }
set { SetValue(WordsProperty, value); }
}
// Using a DependencyProperty as the backing store for Words. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WordsProperty =
DependencyProperty.Register("Words", typeof(string), typeof(SayHello), new PropertyMetadata(default(string)));
//public string Words { get; set; }
I recommend you to use the code snnipet propdp. Tipping propdp and then tab+tab.
Here you can find more information about dependency properties.
Regards
Edit
Changed the default value from string.
In the code below, I have a UserControl that contains an ellipse and a textblock. I'd like to create a reusable control that I can bind to that allows me to set the text based on a string, and changes the fill color between Red/Green based on a boolean.
I can do this now by digging deep into the markup and using some complex binding, but I want to reuse this control in a list and it seemed easier to create a control for the purpose. However, I am not sure where to go next and if I should be creating dependency-properties that tie to the values for Fill and Text, or what.
<UserControl
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"
mc:Ignorable="d"
x:Class="Herp.Derp.View.DeliveryStatusIndicator"
x:Name="UserControl"
d:DesignWidth="91" d:DesignHeight="35">
<Grid x:Name="LayoutRoot">
<StackPanel Orientation="Horizontal">
<Ellipse Width="35" Height="35" Fill="Green">
<Ellipse.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{StaticResource appbar_location_circle}"/>
</Ellipse.OpacityMask>
</Ellipse>
<TextBlock Style="{StaticResource Heading2}"
VerticalAlignment="Center" Margin="3,0,0,0">
<Run Text="FRONT"/>
</TextBlock>
</StackPanel>
</Grid>
</UserControl>
here how you can achieve this
UserControl
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public static readonly DependencyProperty FrontTextProperty = DependencyProperty.Register( "FrontText", typeof(string),typeof(UserControl1), new FrameworkPropertyMetadata(string.Empty));
public string FrontText
{
get { return (string)GetValue(FrontTextProperty); }
set {
SetValue(FrontTextProperty, value);
frontBlock.Text = value;
}
}
public static readonly DependencyProperty EllipseStateProperty = DependencyProperty.Register("EllipseState", typeof(bool), typeof(UserControl1), new FrameworkPropertyMetadata(false));
public bool EllipseState
{
get { return (bool)GetValue(EllipseStateProperty); }
set
{
SetValue(EllipseStateProperty, value);
if (value)
{
ellipse.Fill = new SolidColorBrush( Colors.Green);
}
else
{
ellipse.Fill = new SolidColorBrush(Colors.Red);
}
}
}
}
MainWindow
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 EllipseState="{Binding yourProperty }"/>
<CheckBox Content="CheckBox" HorizontalAlignment="Left" Margin="207,94,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
Yes, to create properties that "parent" XAML can assign bindings to, you need to create aDependencyProperty for each field that you want to bind to.
You would then bind your user control xaml to the backing property for the DP.
Here's what I got for a working solution:
public partial class DeliveryStatusIndicator : UserControl
{
public DeliveryStatusIndicator()
{
InitializeComponent();
}
public static readonly DependencyProperty DeliveryDescriptionProperty = DependencyProperty.Register("DeliveryDescription", typeof(string), typeof(DeliveryStatusIndicator), new FrameworkPropertyMetadata("Default", DescriptionChangedEventHandler));
private static void DescriptionChangedEventHandler(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DeliveryStatusIndicator)d).Desc.Text = (string)e.NewValue;
}
public string DeliveryDescription
{
get { return (string)GetValue(DeliveryDescriptionProperty); }
set
{
SetValue(DeliveryDescriptionProperty, value);
}
}
public static readonly DependencyProperty DeliveryStatusProperty = DependencyProperty.Register("DeliveryStatus", typeof(bool), typeof(DeliveryStatusIndicator), new FrameworkPropertyMetadata(false, StatusChangedEventHandler));
private static void StatusChangedEventHandler(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DeliveryStatusIndicator)d).Indicator.Fill = (bool)e.NewValue ? new SolidColorBrush(Colors.Green) : new SolidColorBrush(Colors.Red);
}
public bool DeliveryStatus
{
get { return (bool)GetValue(DeliveryStatusProperty); }
set
{
SetValue(DeliveryStatusProperty, value);
}
}
}
I have a custom usercontrol with DataContext="{Binding RelativeSource={RelativeSource self}}"
On the code behind i've made a dependency property like:
public static DependencyProperty ElementNameProperty = DependencyProperty.Register("ElementName",
typeof(string),
typeof(ElementControl),
new PropertyMetadata(new PropertyChangedCallback((s, e) => { new Base().OnPropertyChanged("ElementName"); })));
public string ElementName
{
get
{
return (string)base.GetValue(ElementNameProperty);
}
set
{
base.SetValue(ElementNameProperty, value);
}
}
Now when I try to use this usercontrol in my mainpage.xaml and use the following binding: <test.TestControl ElementName="{Binding name}" />, it keeps searching for 'name' property in my custom usercontrol instead of where it should come from?
What am I doing wrong ?
It searches there because you have the DataContext set on the topmost level for your user control. What you would need to do is get rid of the relative binding to self in the user control and specify ElementName in bindings (inside user control). Btw you probably don't need OnPropertyChanged in the PropertyChangedCallback cause DependencyProperties in their nature notify about value changes.
I eventually solved it this way. Not the way I wanted, but it's a (in my eyes) pretty neat solution.
CustomUserControl.xaml
<UserControl x:Class="TestApp.Controls.CustomUserControl"
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"
mc:Ignorable="d"
Width="75"
Height="75">
<Canvas x:Name="LayoutRoot"
Background="Black">
<StackPanel Orientation="Vertical">
<Image x:Name="UCImage"
Width="50"
Height="50"
HorizontalAlignment="Center" />
<TextBlock x:Name="UCText"
HorizontalAlignment="Center" />
</StackPanel>
</Canvas>
</UserControl>
CustomUserControl.xaml.cs
public partial class ElementControl : UserControl
{
#region DependencyProperty ElementNameProperty
public static DependencyProperty ElementNameProperty = DependencyProperty.Register("ElementName",
typeof(string),
typeof(ElementControl),
new PropertyMetadata(new PropertyChangedCallback((s, e) =>
{
//See Here
((ElementControl)s).UCText.Text = e.NewValue as string;
})));
public string ElementName
{
get
{
return (string)base.GetValue(ElementNameProperty);
}
set
{
base.SetValue(ElementNameProperty, value);
}
}
#endregion
}