Closing-EventTrigger on a WPF Window - Problems with DataContext - wpf

I have a view, which initializes a viewmodel inside the windows resources. Further more I give my grid the DataContext.
My question is, how I can add a command to my windows closing event keeping mvvm in memory? I tried the version of this post:
Handling the window closing event with WPF / MVVM Light Toolkit
... but its not working using an event-trigger, because I can't access the viewmodel from outside my grid, so I can't access my command.
Any solution for my problem?
Greetings
Jannik
Edit: Here's my xaml:
<Window x:Class="WpfApplication1.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:WpfApplication1.ViewModels"
xmlns:converter="clr-namespace:WpfApplication1.Converter"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<viewModels:MainWindowViewModel x:Key="ViewModel"/>
</Window.Resources>
<Grid DataContext="{StaticResource ViewModel}">...</Grid>
</Window>

You can reference to members of a static resource this way:
Command="{Binding Path=CloseCommand, Source={StaticResource ViewModel}}"
Here's the complete test project. I used a text box with a binding to ensure data is saved.
<Window x:Class="WpfApplication1.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:WpfApplication1.ViewModels"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<viewModels:MainWindowViewModel x:Key="ViewModel"/>
</Window.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding Path=CloseCommand, Source={StaticResource ViewModel}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid DataContext="{StaticResource ViewModel}">
<TextBox Text="{Binding Txt, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
In ViewModel code, I used a static reference to store data (LastInstance). you can replace it with your own method.
Also I used Command which is a custom implementation of ICommand. If you want I can add the complete implementation here.
public MainWindowViewModel()
{
//save or load here...
if (LastInstance != null) Txt = LastInstance.Txt;
CloseCommand = new Command(o => LastInstance = this);
//...
}
public static ViewModel LastInstance;
//Txt Dependency Property
public string Txt
{
get { return (string)GetValue(TxtProperty); }
set { SetValue(TxtProperty, value); }
}
public static readonly DependencyProperty TxtProperty =
DependencyProperty.Register("Txt", typeof(string), typeof(ViewModel), new UIPropertyMetadata(null));
//CloseCommand Dependency Property
public Command CloseCommand
{
get { return (Command)GetValue(CloseCommandProperty); }
set { SetValue(CloseCommandProperty, value); }
}
public static readonly DependencyProperty CloseCommandProperty =
DependencyProperty.Register("CloseCommand", typeof(Command), typeof(ViewModel), new UIPropertyMetadata(null));

The typical approach to this problem is to have a MainViewModel and set the DataContext of you Window to it. Then define other viewModels in the MainViewModel.
<Window>
<Grid DataContext="{Binding MyGridViewModel}">
</Grid>
<DockPanel DataContext="{Binding AnotherViewModel}">
</DockPanel>
</Window>
in MainWindow constructor:
this.DataContext = new MainViewModel();
in MainViewModel constructor:
this.MyGridViewModel = new OtherViewModel();
This way you have many options to find the desired object through viewModel references.

Related

How to make this named ComboBox in XAML to stop giving a compiler error?

I am trying to make a zoomable toolbar which contains, besides other elements, a ComboBox.
I have a named ComboBox as the content of an instance of a local:ZoomableStackPanel custom control class that inherits from StackPanel and adds a ZoomFactor property which is specified in the IZoomableControl interface. There is a compiler error.
The error seems to be caused by the custom control implementation, but I do not know what is missing. If I replace local:ZoomableStackPanel with a normal StackPanel, there isn't any error. I also tried without any IsSelected ComboBoxItem-s, and the error remains.
MainWindow.xaml
<Window x:Class="cs_wpf_test_14.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:cs_wpf_test_14"
mc:Ignorable="d" Height="60" Width="200">
<local:ZoomableStackPanel Orientation="Horizontal">
<ComboBox Name="MyComboBox">
<ComboBoxItem IsSelected="True">abc</ComboBoxItem>
<ComboBoxItem>def</ComboBoxItem>
<ComboBoxItem>ghi</ComboBoxItem>
</ComboBox>
</local:ZoomableStackPanel>
</Window>
ZoomableStackPanel
XAML
<StackPanel x:Class="cs_wpf_test_14.ZoomableStackPanel"
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:cs_wpf_test_14"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel.LayoutTransform>
<ScaleTransform
ScaleX="{Binding
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=StackPanel},Path=ZoomFactor}"
ScaleY="{Binding
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=StackPanel},Path=ZoomFactor}">
</ScaleTransform>
</StackPanel.LayoutTransform>
</StackPanel>
Code-behind
/// <summary>
/// Interaction logic for ZoomableStackPanel.xaml
/// </summary>
public partial class ZoomableStackPanel : StackPanel, IZoomableControl
{
public ZoomableStackPanel()
{
InitializeComponent();
}
public static readonly DependencyProperty ZoomFactorProperty =
DependencyProperty.Register("ZoomFactor", typeof(decimal), typeof(ZoomableStackPanel),
new FrameworkPropertyMetadata(1M));
public decimal ZoomFactor
{
get
{
return (decimal)GetValue(ZoomFactorProperty);
}
set
{
SetValue(ZoomFactorProperty, value);
}
}
}
The interface
public interface IZoomableControl
{
decimal ZoomFactor { get; set; }
}
I expected the test project to build successfully but there is this compiler error:
Cannot set Name attribute value 'MyComboBox' on element 'ComboBox'. 'ComboBox' is under the scope of element 'ZoomableStackPanel', which already had a name registered when it was defined in another scope.

wpf UserControl command button click binding

I have usercontrol:
<UserControl x:Class="MyApp.Header"
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"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="300" DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}">
<Grid>
<Label Content="{Binding LableContent, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}"></Label>
<Button Command="{Binding Path=AddClick, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
<Image Source="{StaticResource addImage}" Height="20"/>
</Button>
</Grid>
</UserControl>
And dependency property in usercontoror:
public string LableContent
{
get { return (string)GetValue(LableContentProperty); }
set { SetValue(LableContentProperty, value); }
}
public static readonly DependencyProperty LableContentProperty =
DependencyProperty.Register("LableContent", typeof(string), typeof(Header));
public ICommand AddClick
{
get { return (ICommand)GetValue(AddClickProperty); }
set { SetValue(AddClickProperty, value); }
}
public static readonly DependencyProperty AddClickProperty =
DependencyProperty.Register("AddClick", typeof(ICommand), typeof(Header));
I added usercontrol on mainwindow:
<local:Header AddClick="{Binding Path=AddUser_Click}" LableContent="Users"></local:Header>
And add click event on MainWindow.cs
private void AddUser_Click(object sender, RoutedEventArgs e)
{
}
The problem is that the Lable is being filled, but the command click the button is not called. What am I doing wrong?
There are two things you need to set
Specify the DataContext for window.xaml and relative source for the AddClick command so that AddUser_Click can be found on Window.
Update your Window.xaml AddClick binding to
<local:Header AddClick="{Binding Path=DataContext.AddUser_Click, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}}" LableContent="Users"/>
and set DataContext of Window.xaml to Window.xaml.cs by adding this to your MainWindow constructor
this.DataContext = this;
Doing the above step will ensure that the AddUser_Click property can be found correctly.
All dependency properties when binded tries to find a property in the DataContext and not method. So, the command should be a property on window.cs of type ICommand and it should be given a method in the constructor.
To implement this most people use http://www.wpftutorial.net/delegatecommand.html. Simply copy this to a new file.
In your MainWindow.xaml.cs, add this
AddUser_Click = new DelegateCommand(AddUserMethod);
You can now add a method named AddUserMethod in the same file and it will be called whenever you click the button from the User Control!!

Binding Dependency Property to View Model

I have two user controls defined as follows:
User Control 1
XAML
<UserControl x:Class="TestBindings.UserControlOne"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestBindings">
<UserControl.DataContext>
<local:UserControlOneViewModel/>
</UserControl.DataContext>
<StackPanel>
<TextBlock Text="{Binding MyProperty}"/>
<local:UserControlTwo PropertyTwo="{Binding DataContext.MyProperty, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
</StackPanel>
</UserControl>
Code Behind
public partial class UserControlOne : UserControl
{
public UserControlOne()
{
InitializeComponent();
}
}
User Control 2
XAML
<UserControl x:Class="TestBindings.UserControlTwo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestBindings">
<UserControl.DataContext>
<local:UserControlTwoViewModel/>
</UserControl.DataContext>
<TextBlock Name="TextBlock" Text="{Binding PropertyTwo}"/>
</UserControl>
Code Behind
public partial class UserControlTwo : UserControl
{
public static readonly DependencyProperty PropertyTwoProperty =
DependencyProperty.Register("PropertyTwo", typeof (string), typeof (UserControlTwo),
new FrameworkPropertyMetadata("Default", OnPropertyTwoChanged));
public UserControlTwo()
{
InitializeComponent();
var propertyTwoBinding = new Binding("PropertyTwo") {Mode = BindingMode.TwoWay};
SetBinding(PropertyTwoProperty, propertyTwoBinding);
}
public string PropertyTwo
{
get { return (string) GetValue(PropertyTwoProperty); }
set { SetValue(PropertyTwoProperty, value); }
}
private static void OnPropertyTwoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var userControlTwo = (UserControlTwo) d;
userControlTwo.PropertyTwo = (string) e.NewValue;
}
}
In UserControlTwo's constructor I bind the dependency property PropertyTwoProperty to a property in the associated ViewModel. I ultimately want to bind this to a property in the ViewModel of UserControlOne, hence UserControlOne xaml
<local:UserControlTwo PropertyTwo="{Binding DataContext.MyProperty, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
However this never seems to get set. Any ideas where I may be going wrong?
I think you are trying to pass a property from the datacontext of UserControlOne to a DependencyProperty in UserControlTwo.
In that case you use the below approach and also remove the setbinding in the code in your UserControl2 Constructor. Let me know if this is what you are looking for.
<UserControl x:Class="TestBindings.UserControlOne"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="userControl"
xmlns:local="clr-namespace:TestBindings">
<UserControl.DataContext>
<local:UserControlOneViewModel/>
</UserControl.DataContext>
<StackPanel>
<TextBlock Text="{Binding MyProperty}"/>
<local:UserControlTwo PropertyTwo="{Binding DataContext.MyProperty, ElementName=userControl,Mode=TwoWay}"/>
</StackPanel>
</UserControl>

Accessing dependency property in the same control xaml

In a Wpf Application i have a main window.
I have added a user control to the same project.
In the user control's .xaml.cs file a Dependency property ( "Value" name of the property ) is added.
I would like to access the defined dependency property in the usercontrol.xaml.
I know i can do the same while creating the control instance either in window.xaml or some other user control.
But is it possible to access the dependency property defined in .xaml.cs in .xaml?
Question updated based on Vivs answer
Ok. I mentioned my question wrongly. Nevertheless even i was not aware of accessing. But my actual intended question is it possible to set the dependency property from .xaml. some thing like from the example given above,
<Grid CustomBackground ="{Binding Path= BackgroundColor}" />
Or
<Grid CustomBackground ="Blue" />
Is it possible to set the custom dependency properties like this in the same .xaml?
Yes it is possible.
something like:
.xaml
<UserControl x:Class="MvvmLight26.UserControl1"
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:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}, Path=CustomBackground}" />
</UserControl>
and .xaml.cs:
public partial class UserControl1 : UserControl {
public static readonly DependencyProperty CustomBackgroundProperty =
DependencyProperty.Register(
"CustomBackground",
typeof(Brush),
typeof(UserControl1),
new FrameworkPropertyMetadata(Brushes.Tomato));
public UserControl1() {
InitializeComponent();
}
public Brush CustomBackground {
get {
return (Brush)GetValue(CustomBackgroundProperty);
}
set {
SetValue(CustomBackgroundProperty, value);
}
}
}
Alternate:
If you say have the DataContext of the UserControl as itself like:
public UserControl1() {
InitializeComponent();
DataContext = this;
}
then in your xaml you could just go with:
<Grid Background="{Binding Path=DataContext.CustomBackground}" />
Update:
For the new question,
Not quite directly.
You can "set" the value if the custom DP is registered as an attached property(Do remember an attached property is not the same as a normal DP in it's behavior and scope.)
If you want to keep it as a normal DP, then you can keep UserControl1 from the original answer same as it is(just the DP part. You need to remove the xaml part of it and make it a non-partial class in the code-behind) and then derive it to a new UserControl.
something like:
<local:UserControl1 x:Class="MvvmLight26.UserControl2"
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:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
CustomBackground="Blue"
mc:Ignorable="d">
<Grid />
</local:UserControl1>
You can ofc name UserControl1 as something like "BaseUserControl" or so to make it obvious that it's not intended for direct usage.
You can set the value from the UserControl.Style in the same xaml as well.
xaml:
<UserControl x:Class="MvvmLight26.UserControl1"
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:local="clr-namespace:MvvmLight26"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Style>
<Style>
<Setter Property="local:UserControl1.CustomBackground"
Value="Blue" />
</Style>
</UserControl.Style>
<Grid Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:UserControl1}}, Path=CustomBackground}" />
</UserControl>

Silverlight UserControl Custom Property Binding

What is the proper way to implement Custom Properties in Silverlight UserControls?
Every "Page" in Silverlight is technically a UserControl (they are derived from the UserControl class). When I say UserControl here, I mean a Custom UserControl that will be used inside many different pages in many different scenarios (similar to an ASP.NET UserControl).
I would like the Custom UserControl to support Binding and not rely on the Name of the Property it is binding to, to always be the same. Instead, I would like the UserControl itself to have a property that the Controls inside the UserControl bind to, and the ViewModels outside the UserControl also bind to. (please see the example below)
Binding within the UserControl works, Binding within the MainPage works, The Binding I set up between the MainPage and the UserControl does not work. Specifically this line:
<myUserControls:MyCustomUserControl x:Name="MyCustomControl2"
SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}"
Width="200" Height="50" />
example output:
MainPage.xaml
<UserControl x:Class="SilverlightCustomUserControl.MainPage"
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:myUserControls="clr-namespace:SilverlightCustomUserControl"
mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Canvas x:Name="LayoutRoot">
<StackPanel Orientation="Vertical">
<TextBlock Text="UserControl Binding:" Width="200"></TextBlock>
<myUserControls:MyCustomUserControl x:Name="MyCustomControl2" SelectedText="{Binding MainPageSelectedText, Mode=TwoWay}" Width="200" Height="50" />
<TextBlock Text="MainPage Binding:" Width="200"></TextBlock>
<TextBox Text="{Binding MainPageSelectedText, Mode=TwoWay}" Width="200"></TextBox>
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding MainPageSelectedText}" Width="200" Height="24"></TextBlock>
</Border>
</StackPanel>
</Canvas>
</UserControl>
MainPage.xaml.cs
namespace SilverlightCustomUserControl
{
public partial class MainPage : UserControl, INotifyPropertyChanged
{
//NOTE: would probably be in a ViewModel
public string MainPageSelectedText
{
get { return _MainPageSelectedText; }
set
{
string myValue = value ?? String.Empty;
if (_MainPageSelectedText != myValue)
{
_MainPageSelectedText = value;
OnPropertyChanged("MainPageSelectedText");
}
}
}
private string _MainPageSelectedText;
public MainPage()
{
InitializeComponent();
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
PropertyChangedEventHandler ph = this.PropertyChanged;
if (ph != null)
ph(this, new PropertyChangedEventArgs(name));
}
#endregion
}
}
MyCustomUserControl.xaml
<UserControl
x:Class="SilverlightCustomUserControl.MyCustomUserControl"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<StackPanel>
<TextBox Text="{Binding SelectedText, Mode=TwoWay}" />
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding SelectedText}" Height="24"></TextBlock>
</Border>
</StackPanel>
</Grid>
</UserControl>
MyCustomUserControl.xaml.cs
namespace SilverlightCustomUserControl
{
public partial class MyCustomUserControl : UserControl
{
public string SelectedText
{
get { return (string)GetValue(SelectedTextProperty); }
set { SetValue(SelectedTextProperty, value); }
}
public static readonly DependencyProperty SelectedTextProperty =
DependencyProperty.Register("SelectedText", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata("", SelectedText_PropertyChangedCallback));
public MyCustomUserControl()
{
InitializeComponent();
}
private static void SelectedText_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//empty
}
}
}
References (how I got this far):
use DependencyPropertys:
http://geekswithblogs.net/thibbard/archive/2008/04/22/wpf-custom-control-dependency-property-gotcha.aspx
use DependencyPropertys, add x:Name to your UserControl - add Binding with ElementName, set Custom property again in the PropertyChangedCallback method:
Setting Custom Properties in UserControl via DataBinding
don't use custom properties, rely on underlying datacontext names (I do not like this solution):
wpf trouble using dependency properties in a UserControl
I understand it as the reason your control is not receiving the new value from the maim page is that you are setting the DataContext of the control. If you hadn't then the control's DataContext will be inherited from its parent, the main page in this case.
To get this to work I removed you control's DataContext setting, added an x:Name to each control and set the binding in the constructor of the control using the [name].SetBinding method.
I did the binding in the ctor as I couldn't figure out a way of setting the Source property of the declarative binding in the xaml to Self. i.e. {Binding SelectedText, Mode=TwoWay, Source=[Self here some how]}. I did try using RelativeSource={RelativeSource Self} with no joy.
NOTE: All this is SL3.
The Issue was the UserControl was throwing a DataBinding error (visible in the Output window while debugging)
Because The UserControl's DataContext was set to "Self" in its own xaml, it was looking for the MainPageSelectedText within its own context (it was not looking for the MainPageSelectedText within the "MainPage" which is where you might think it would look, because when you are physically writing/looking at the code that is what is in "context")
I was able to get this "working" by setting the Binding in the code behind. Setting the binding in the code behind is the only way to set the UserControl itself as the "Source" of the binding. But this only works if the Binding is TwoWay. OneWay binding will break this code. A better solution altogether would be to create a Silverlight Control, not a UserControl.
See Also:
http://social.msdn.microsoft.com/Forums/en-US/silverlightcontrols/thread/052a2b67-20fc-4f6a-84db-07c85ceb3303
http://msdn.microsoft.com/en-us/library/cc278064%28VS.95%29.aspx
MyCustomUserControl.xaml
<UserControl
x:Class="SilverlightCustomUserControl.MyCustomUserControl"
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">
<Grid>
<StackPanel>
<TextBox x:Name="UserControlTextBox" />
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock x:Name="UserControlTextBlock" Height="24"></TextBlock>
</Border>
</StackPanel>
</Grid>
</UserControl>
MyCustomUserControl.xaml.cs
namespace SilverlightCustomUserControl
{
public partial class MyCustomUserControl : UserControl
{
public string SelectedText
{
get { return (string)GetValue(SelectedTextProperty); }
set { SetValue(SelectedTextProperty, value); }
}
public static readonly DependencyProperty SelectedTextProperty =
DependencyProperty.Register("SelectedText", typeof(string), typeof(MyCustomUserControl), new PropertyMetadata("", SelectedText_PropertyChangedCallback));
public MyCustomUserControl()
{
InitializeComponent();
//SEE HERE
UserControlTextBox.SetBinding(TextBox.TextProperty, new Binding() { Source = this, Path = new PropertyPath("SelectedText"), Mode = BindingMode.TwoWay });
UserControlTextBlock.SetBinding(TextBlock.TextProperty, new Binding() { Source = this, Path = new PropertyPath("SelectedText") });
//SEE HERE
}
private static void SelectedText_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//empty
}
}
}
Instead of binding data context to self, you can set the binding in xaml by adding an x:Name for the user control and then binding in the user control xaml follows:
<UserControl
x:Class="SilverlightCustomUserControl.MyCustomUserControl"
x:Name="myUserControl
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">
<Grid>
<StackPanel>
<TextBox Text="{Binding SelectedText, ElementName=myUserContol, Mode=TwoWay}" />
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding SelectedText,ElementName=myUserControl}" Height="24"></TextBlock>
</Border>
</StackPanel>
</Grid>
</UserControl>

Resources