WPF UserControl DependencyProperty use in XAML or by binding

Multi tool use
WPF UserControl DependencyProperty use in XAML or by binding
I want a universal UserControl where i can set a property either by setting its value in XAML directly or by binding it to some model property.
Just like TextBlock Text property works.
Right now i just have the bare simple UserControl, it has a single DependencyProperty TxT and a TextBlock Text property bound to it. No other code present.
If i set TxT in XAML on main window it wont work, binding works.
If i add PropertyChangedCallback to that DependencyProperty it works also in XAML.
So the question, is it mandatory to have PropertyChangedCallback for each property if i want to be able to set it directly in XAML?
This is not clear to me, most don't mention about it, but it also forces me to adding internal control names to change their value in PropertyChangedCallback.
The code is below.
Can it be done some other way?
MainWindow
<Window
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:WpfAppDpBare" xmlns:Model="clr-namespace:WpfAppDpBare.Model" x:Class="WpfAppDpBare.MainWindow"
Background="CadetBlue"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Window.DataContext>
<Model:MainModel/>
</Window.DataContext>
<Grid>
<local:UserControlSample TxT="DIRECT TXT" HorizontalAlignment="Center" VerticalAlignment="Center" Height="125" Width="125" Margin="10,34,659,262"/>
<TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Direct" VerticalAlignment="Top" FontSize="14" FontWeight="Bold"/>
<TextBlock HorizontalAlignment="Left" Margin="203,10,0,0" TextWrapping="Wrap" Text="Binding" VerticalAlignment="Top" FontSize="14" FontWeight="Bold"/>
<local:UserControlSample DataContext="{Binding UCData}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="125" Width="125" Margin="203,34,466,262"/>
</Grid>
public partial class MainWindow:Window {
public MainWindow() {
InitializeComponent();
}
}
UserControl
<UserControl x:Class="WpfAppDpBare.UserControlSample"
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:WpfAppDpBare"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Background="White">
<Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding TxT,FallbackValue=...,TargetNullValue=...}" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" FontWeight="Bold"/>
</Grid>
public partial class UserControlSample:UserControl {
public UserControlSample() {
InitializeComponent();
}
public string TxT {
get { return (string)GetValue(TxTProperty); }
set { SetValue(TxTProperty, value); }
}
// Using a DependencyProperty as the backing store for TxT. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TxTProperty =
DependencyProperty.Register("TxT", typeof(string), typeof(UserControlSample), new PropertyMetadata());
}
Models
public class MainModel:ViewModelBase {
/// <summary>
/// The <see cref="UCData" /> property's name.
/// </summary>
public const string UCDataPropertyName = "UCData";
private UCModel uCModel = null;
/// <summary>
/// Sets and gets the UCData property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public UCModel UCData {
get {
return uCModel;
}
set {
if(uCModel == value) {
return;
}
uCModel = value;
RaisePropertyChanged(UCDataPropertyName);
}
}
public MainModel() {
UCData = new UCModel() { TxT = "BINDING TXT" };
}
}
public class UCModel:ViewModelBase {
/// <summary>
/// The <see cref="TxT" /> property's name.
/// </summary>
public const string TxTPropertyName = "TxT";
private string _TxT = null;
/// <summary>
/// Sets and gets the TxT property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public string TxT {
get {
return _TxT;
}
set {
if(_TxT == value) {
return;
}
_TxT = value;
RaisePropertyChanged(TxTPropertyName);
}
}
}
Full bare project https://wetransfer.com/downloads/199f3db5d183e64cf9f20db4225d4c9820180702001102/f4f61b
As u can see in the project binding works, direct property text not.
I want it all contained in the usercontrol, so i either set usercontrol property value in xaml or bind to it, without another addition in the mainwindow xaml or code.
@ASh It is basically the same as stackoverflow.com/questions/4368808/… It is the most simple code u can do, if my description is not enough i can provide a bare project.
– Programista
Jul 1 at 18:55
that one is resolved. if yours doesn't work, then smth is different
– ASh
Jul 1 at 19:01
Another stackoverflow.com/questions/50835495/… post I have shows creation of a user custom control with custom dependency properties and how setting in xaml can be done. The text values can / should also be completely valid through standard binding the model you are trying to bind to... See if that link helps make sense of the steps...
– DRapp
Jul 1 at 19:03
Show your code, otherwise we can't help you. That said, "is it mandatory to have PropertyChangedCallback for each property if i want to be able to set it directly in XAML?" - no, definitely not. It doesn't matter whether there is such a callback or not.
– Clemens
Jul 1 at 19:10
1 Answer
1
You are not binding the TextBlock's Text
property to the TxT
property of the UserControl.
Text
TxT
Set the Binding's RelativeSource
<TextBlock Text="{Binding TxT,
RelativeSource={RelativeSource AncestorType=UserControl}, ...}" .../>
or assign a x:Name
to the UserControl and use an ElementName Binding.
x:Name
Then, instead of setting the UserControl's DataContext by
<local:UserControlSample DataContext="{Binding UCData}" .../>
bind its TxT property:
<local:UserControlSample TxT="{Binding UCData.TxT}" .../>
EDIT: In order to bind directly to the properties of the object in its DataContext, as intended with
<local:UserControlSample DataContext="{Binding UCData}" .../>
you do not need to declare any properties at all in the UserControl. Remove the TxT dependency property declaration, and bind the elements in the UserControl's XAML directly, as you already did:
<TextBlock Text="{Binding TxT, ...}"/>
Note however that this is not how UserControl usually work. Yours does now depend on a specific view model type, and can't be reused with other view models.
That is not true, i'm binding Text property to the Txt as u can see in the question code samples and available project files, if i change it like u propose or with ElementName then direct property set will work, but binding will not. It needs to work in both cases.
– Programista
Jul 2 at 11:27
@Programista: You are setting the
TxT
dependency property to "DIRECT TXT" but you don't display this value somewhere. The value being displayed is the value of the TxT
property of the UCModel
.– mm8
Jul 2 at 11:50
TxT
TxT
UCModel
@Programista There are two TxT properties, one in the UserControl, the other in the view model. The problem and solution would be easier to understand if you would use different names for these properties.
– Clemens
Jul 2 at 14:20
@Clemens It cannot have different name as this is the binding name it need to bind to, so model needs the same name.
– Programista
Jul 2 at 22:45
@Clemens I dont want to do TxT="{Binding UCData.TxT}" as if i will have many more properties i want to bind them to a single model object via DataContext, not repeating that code for every property, besides it shoud work with DataContext, everyone says it is simple, but no one have a working solution, even on other similar questions. Well in the sample project binding works via DataContext, it is the direct TxY xaml value that is not working. I want both.
– Programista
Jul 2 at 22:51
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
mind sharing a Minimal, Complete, and Verifiable example?
– ASh
Jul 1 at 18:51