I'm trying to set the fill property of several instances of the same usercontrol from XAML in order to distinguish them. I'm using a dependency property in the C# codebehind of the control and referring to that in the XAML when I instantiate the control. Here's a simplified example of what I've tried, first the XAML of the user control:
<UserControl x:Class="RectangleFillUserControlTest.RectangleFillTest"
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="50" d:DesignWidth="150">
<Grid>
<Rectangle x:Name="rect" HorizontalAlignment="Left" Height="50" Stroke="Black" VerticalAlignment="Top" Width="150"/>
</Grid>
</UserControl>
Now the codebehind:
namespace RectangleFillUserControlTest
{
public partial class RectangleFillTest : UserControl
{
SolidColorBrush fillBrush;
public static readonly DependencyProperty FillColourProperty = DependencyProperty.Register
("FillColour", typeof(string), typeof(RectangleFillTest), new PropertyMetadata(string.Empty));
public string FillColour
{
get { return (string)GetValue(FillColourProperty); }
set
{
SetValue(FillColourProperty, value);
if (value == "red") fillBrush = new SolidColorBrush(Colors.Red);
else fillBrush = new SolidColorBrush(Colors.Green);
rect.Fill = fillBrush;
}
}
public RectangleFillTest()
{
InitializeComponent();
}
}
}
I instantiate the control in the main window and try to set the fill colour to red:
<Window x:Class="RectangleFillUserControlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:RectangleFillUserControlTest"
Title="MainWindow" Height="350" Width="525">
<Grid Background="#FF1D2CC3">
<local:RectangleFillTest FillColour="red"/>
</Grid>
</Window>
But the rectangle remains unfilled, even when I run the project. Can anyone help please?
Cheers,
Tim
There are two things wrong with your dependency property.
First, its type should be Brush, not string, because that is the type used by properties of WPF controls like Shape.Fill or Control.Background. WPF provides automatic type conversion from strings like "Red" or "#FFFF0000" in XAML to type Brush.
Second, you should not have anything else than a call to SetValue in the setter method of the CLR wrapper. The reason is explained in the XAML Loading and Dependency Properties article on MSDN:
Because the current WPF implementation of the XAML processor behavior
for property setting bypasses the wrappers entirely, you should not
put any additional logic into the set definitions of the wrapper for
your custom dependency property. If you put such logic in the set
definition, then the logic will not be executed when the property is
set in XAML rather than in code.
So your dependency property declaration should look like this:
public static readonly DependencyProperty FillBrushProperty =
DependencyProperty.Register(
"FillBrush", typeof(Brush), typeof(RectangleFillTest));
public Brush FillBrush
{
get { return (Brush)GetValue(FillBrushProperty); }
set { SetValue(FillBrushProperty, value); }
}
To react to property changes, you would now register a PropertyChangedCallback with property metadata. But you don't need to do that here, because you could simply bind the property in the UserControl's XAML like this:
<Rectangle Fill="{Binding FillBrush,
RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" ... />
I will explain why is is not working and how to solve.
1.- A Dependency Property is only called when the usercontrol has that dependency property in the visual tree.
In case you want to do in that way, you need to add for instance :
new PropertyMetadata(string.Empty, ValueChanged));
and there change the value:
public static readonly DependencyProperty FillColourProperty = DependencyProperty.Register
("FillColour", typeof(string), typeof(RectangleFillTest), new PropertyMetadata(string.Empty, ValueChanged));
private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as RectangleFillTest;
var fillBrush = new SolidColorBrush();
if (control.FillColour == "red")
fillBrush = new SolidColorBrush(Colors.Red);
else
fillBrush = new SolidColorBrush(Colors.Green);
control.rect.Fill = fillBrush;
}
public string FillColour
{
get
{
return (string)GetValue(FillColourProperty);
}
set
{
SetValue(FillColourProperty, value);
}
}
That is explicit for your logic, in case you need a more generic code for any color, etc using binding the property to the rectangle, just tell me.
You need to bind your Dependency Property to the Fill property of your Rectangle in the xaml of your UserControl. You'll have Something like this :
<Rectangle x:Name="rect" Fill="{Binding FillColour, RelativeSource={RelativeSource FindAncestor, AncestorType=RectangleFillTest}}" HorizontalAlignment="Left" Height="50" Stroke="Black" VerticalAlignment="Top" Width="150"/>
Also, in your dependency property, it's type should be Brush, and not String.
Related
I'm most probably missing something obvious as I'm new to WPF development. I'm trying to create a Windows Phone 8.1 application and for my use I want to create a custom user control that contains hero information and hero icon (simple game-related information lookup app).
I have created a usercontrol with name HeroInformationControl and then defined an image and textblock in XAML. Looking up through various resources online I created it as follows:
<UserControl Name="HeroInformationControl"
x:Class="DotaHelper.HeroInformation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DotaHelper"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="50"
d:DesignWidth="400">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image
HorizontalAlignment="Left"
Height="Auto"
Stretch="Fill"
VerticalAlignment="Top"
Width="Auto" Source="{Binding ElementName=HeroInformationControl, Path=HeroImage}"
/>
<TextBlock
Grid.ColumnSpan="2"
HorizontalAlignment="Center"
Height="50"
Grid.Column="1"
TextWrapping="Wrap"
Text="{Binding ElementName=HeroInformationControl, Path=HeroName}"
VerticalAlignment="Center"
Width="300"/>
Then, HeroInformation.xaml.cs:
public partial class HeroInformation
{
public HeroInformation()
{
this.InitializeComponent();
this.DataContext = this;
}
public static readonly DependencyProperty HeroNameProperty =
DependencyProperty.Register("HeroName", typeof(string), typeof(string), new PropertyMetadata(""));
public string HeroName
{
get { return (string)GetValue(HeroNameProperty); }
set { SetValue(HeroNameProperty, value); }
}
public static readonly DependencyProperty HeroImageProperty =
DependencyProperty.Register("HeroImage", typeof(string), typeof(string), new PropertyMetadata(""));
public string HeroImage
{
get { return (string)GetValue(HeroImageProperty); }
set { SetValue(HeroImageProperty, value); }
}
}
MainPage.xaml, HeroInformation object:
<local:HeroInformation
x:Name="HeroInformation1"
HorizontalAlignment="Left"
Height="Auto"
VerticalAlignment="Top"
Width="200"
/>
And from the UI thread in MainPage.xaml.cs:
HeroInformation1.HeroImage = hero.IMGurl;
HeroInformation1.HeroName = hero.Heroname;
Sorry for a long code but I have virtually no idea where the problem is.
As a note: hero.IMGUrl and hero.Heroname properties are both of string.
Also if I add to Mainpage.xaml properties by hand (HeroImage and HeroName) it loads.
Any help to understand what's wrong would be appreciated - also, if you spot something that is far from best programming practice I'd be grateful for tips.
Never. Ever. Ever. Do this:
this.DataContext = this;
Instead, give your UserControl an x:Name in your XAML file. Like this:
<UserControl x:Name="usr" ... >
This will allow you to bind to your Dependency Properties using the following binding:
Text="{Binding DataContext.HeroName, ElementName=usr}"
Alternatively, you can bind the UserControl to itself using the following:
DataContext="{Binding RelativeSource={RelativeSource Self}}"
And your binding will look like this:
Text="{Binding HeroName}"
EDIT: Also, as Juan has noticed, your Dependency Property declarations are incorrect:
public string HeroName
{
get { return (string)GetValue(HeroNameProperty); }
set { SetValue(HeroNameProperty, value); }
}
// Using a DependencyProperty as the backing store for HeroName. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeroNameProperty =
DependencyProperty.Register("HeroName", typeof(string), typeof(HeroInformation), new PropertyMetadata(null));
Pro-tip: Use propdp -> Tab -> Tab to declare a dependency property.
the only thing you missed was:
public static readonly DependencyProperty HeroNameProperty =
DependencyProperty.Register("HeroName", typeof(string), typeof(HeroInformation), new PropertyMetadata(""));
typeof(HeroInformation)
the rest is perfect and the way to do it. Might be the image give some issue (I cannot remember in all platforms (WPF,WP, UWP) if it is right use String for URI.
I have a user WPF UserControl which is just a grid with an Image in it and I'm bidning the Image to a ImageSource Dependency Property named Source.
<UserControl x:Class="ImageOnlyClient.MyImage"
x:Name="MyImageControl"
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="300" d:DesignWidth="300">
<Grid Name="MainGrid">
<Border Name="MyImageBorder" BorderThickness="2" BorderBrush="Orange">
<Image Name="MyImage" VerticalAlignment="Top" Opacity="1"
RenderOptions.BitmapScalingMode="NearestNeighbor"
Source="{Binding Path=Source, Mode=OneWay}" />
</Border>
</Grid>
In the UserControl codebehind my class is defined as follows:
public partial class MyImage : UserControl
{
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
#region Source DependencyProperty
public static readonly DependencyProperty SourceProperty;
private static void SourceProperty_PropertyChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs e)
{
//To be called whenever the DP is changed.
System.Diagnostics.Debug.WriteLine("SourceProperty changed is fired");
}
private static bool SourceProperty_Validate(object Value)
{
//Custom validation block which takes in the value of DP
//Returns true / false based on success / failure of the validation
//MessageBox.Show(string.Format("DataValidation is Fired : Value {0}", Value));
return true;
}
private static object SourceProperty_CoerceValue(DependencyObject dobj, object Value)
{
//called whenever dependency property value is reevaluated. The return value is the
//latest value set to the dependency property
//MessageBox.Show(string.Format("CoerceValue is fired : Value {0}", Value));
return Value;
}
#endregion
static MyImage()
{
SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(MyImage),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Journal,
new PropertyChangedCallback(SourceProperty_PropertyChanged),
new CoerceValueCallback(SourceProperty_CoerceValue),
false, UpdateSourceTrigger.PropertyChanged),
new ValidateValueCallback(SourceProperty_Validate));
}
public MyImage()
{
InitializeComponent();
}
}
In a Window I try to use the Image as follows and Bind it's source property to a WritableBitmap (MyClient.ImageMgr.ImageSource) which I can successfully bind to a regular Image control.
<local:MyImage x:Name="imgPrimaryImage" Height="768" Width="1024" Grid.Column="1" Grid.RowSpan="2"
Source="{Binding Path=MyClient.ImageMgr.ImageSource}" />
Any help on what's going on here would be greatly appreciated. I'm getting the following binding error:
System.Windows.Data Error: 40 : BindingExpression path error: 'Source' property not found on 'object' ''ImageOnly' (Name='')'. BindingExpression:Path=Source; DataItem='ImageOnly' (Name=''); target element is 'Image' (Name='MyImage'); target property is 'Source' (type 'ImageSource')
You're attempting to bind the Image's "Source" to a property on the parent UserControl, but if you don't specify a source (I mean a binding source ... the terminology here is confusing), then the runtime will look for the property on the default data context. I would infer from the error message that a class of type "ImageOnly" is the inherited data context in your user control.
You probably just want to specify a relative source, like this:
<Image ...
Source="{Binding
RelativeSource={RelativeSource AncestorType=UserControl},
Path=Source,
Mode=OneWay}"
/>
I finally got it to work #McGarnagle's suggestion worked, but in the mean time I had added a DataContext=this in the UserControl's constructor which was messing up the DataContext of the UserControl
I have a UserControl that will be reused throughout an application we are developing.
We are using a framework based on MVVMLight.
For the sake of simplicity lets say the user control contains only one textbox and exposes one dependency property named "Quantity". The textbox on the user control is databound to the dependency property "Quantity".
When the user control is used on a view, the "Quantity" dependency property of the usercontrol is databound to a property in a ViewModel. (This ViewModel is the datacontext of our view by way of the MVVMLight ViewModelLocator).
This all works great! The bindings work, properties are set like I would expect. All is well until it comes to validation.
We are using DataAnnotations to decorate our ViewModel properties. The ViewModel contains a custom implementation of INotifyDataErrorInfo. We have implemented custom styles for most input controls to show a red border around the control, and a message next to the control displaying the validation error message. All of this works great in a normal case (eg. Textbox on a View bound to a property in a view model).
When I attempt the same approach using this user control, what I end up with is a red border around the entire user control and no error indication on the actual textbox. It appears that the fact that there is an error is being reflected in the UI, but it's just not making it to the control I want it to.
I've searched on stackoverflow for this problem, of those questions with solutions, none seem to work for my situation.
My first guess is that because the actual textbox is bound directly to the dependency property itself and not the property on my view model, it is not being notified properly of the errors generated. Is there some way to propogate those errors generated in the viewmodel through the usercontrol and then to the textbox?
Any help or suggestions you can give would be great, thanks.
Here is the UserControl xaml.
<UserControl x:Class="SampleProject.UserControls.SampleControl"
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" x:Name="sampleControl"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=sampleControl}">
<TextBox Text="{Binding Path=Quantity, ValidatesOnDataErrors=True}" Width="100" Height="30" />
</Grid>
</UserControl>
The UserControl code behind.
public partial class SampleControl : UserControl
{
public SampleControl()
{
InitializeComponent();
}
public static readonly DependencyProperty QuantityProperty =
DependencyProperty.Register("Quantity", typeof(int?), typeof(SampleControl),
new FrameworkPropertyMetadata{DefaultValue=null, BindsTwoWayByDefault = true});
public int? Quantity
{
get { return (int?)GetValue(QuantityProperty); }
set { SetValue(QuantityProperty, value); }
}
}
Used on a view.
<userControls:SampleControl Grid.Row="1" Quantity="{Binding Path=Quantity, ValidatesOnDataErrors=True}" Height="60" Width="300"/>
The ViewModel property.
[Required(ErrorMessage = "Is Required")]
[Range(5, 10, ErrorMessage = "Must be greater than 5")]
public int? Quantity
{
get { return _quantity; }
set { Set(() => Quantity, ref _quantity, value); }
}
private int? _quantity;
(*Note, The Set method in the setter is just a helper method in the base viewmodel that sets the backing property and raises the PropertyChanged event for it.)
Try removing the DataContext from the UserControl. Instead of setting that, Bind directly from the TextBox to the actual property using a RelativeSource Binding:
<TextBox Text="{Binding Quantity, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type YourControlNamespace:SampleControl,
ValidatesOnDataErrors=True}}}" Width="100" Height="30" />
UPDATE >>>
Failing that, as long as the view models that are bound to this property will always have a property of the same name to bind to, you can get this Binding to search through parents' DataContexts like this:
<TextBox Text="{Binding Quantity, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorLevel=2, ValidatesOnDataErrors=True}}}" Width="100" Height="30" />
You will need to change the 2 to be the correct number of parent elements that the TextBox has before reaching the control with access to the correct property. For example, using a level of 2 means that the Framework will try to find a property named Quantity to Bind to in the DataContext of the TextBoxs parent's parent control. It is trickier getting this working with AncestorLevel though as I believe that 'hidden' elements like Grids are not included as parents.
You need to pick up the bindings set on the usercontrol and place them on the controls, there is no need to bind the usercontrol to it's own DataContext.
This can be done after the usercontrol is loaded.
To prevent a red border round the user control, remove the default error template:
Validation.ErrorTemplate="{x:Null}"
Sample user control XAML:
UserControl x:Class="DxUserControlValidation.MyUserControl"
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"
Validation.ErrorTemplate="{x:Null}"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel Orientation="Vertical">
<TextBlock Text="Value 1:" Margin="2"/>
<TextBox Name="txtBox1" Margin="2"/>
<TextBlock Text="Value 2:" Margin="2"/>
<TextBox Name="txtBox2" Margin="2"/>
</StackPanel>
public partial class MyUserControl : UserControl
{
public static readonly DependencyProperty Value1Property;
public static readonly DependencyProperty Value2Property;
static MyUserControl()
{
Value1Property = DependencyProperty.Register("Value1", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata { DefaultValue = null, BindsTwoWayByDefault = true });
Value2Property = DependencyProperty.Register("Value2", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata { DefaultValue = null, BindsTwoWayByDefault = true });
}
public MyUserControl()
{
InitializeComponent();
Loaded += (s, e) =>
{
Binding value1Binding = BindingOperations.GetBinding(this, Value1Property);
if (value1Binding != null) txtBox1.SetBinding(TextBox.TextProperty, value1Binding);
Binding value2Binding = BindingOperations.GetBinding(this, Value2Property);
if (value2Binding != null) txtBox2.SetBinding(TextBox.TextProperty, value2Binding);
};
}
public string Value1
{
get { return (string)GetValue(Value1Property); }
set { SetValue(Value1Property, value); }
}
public string Value2
{
get { return (string)GetValue(Value2Property); }
set { SetValue(Value2Property, value); }
}
}
If there is no binding, you van assign the value directly to the control:
if (value2Binding != null) txtBox2.SetBinding(TextBox.TextProperty, value2Binding);
else txtBox2.Text = Value2;
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
}
How can I access the public variable which in Sample.xaml.cs file like asp.net <%=VariableName%>?
There are a few ways to do this.
Add your variable as a resource from codebehind:
myWindow.Resources.Add("myResourceKey", myVariable);
Then you can access it from XAML:
<TextBlock Text="{StaticResource myResourceKey}"/>
If you have to add it after the XAML gets parsed, you can use a DynamicResource above instead of StaticResource.
Make the variable a property of something in your XAML. Usually this works through the DataContext:
myWindow.DataContext = myVariable;
or
myWindow.MyProperty = myVariable;
After this, anything in your XAML can access it through a Binding:
<TextBlock Text="{Binding Path=PropertyOfMyVariable}"/>
or
<TextBlock Text="{Binding ElementName=myWindow, Path=MyProperty}"/>
For binding, if DataContext is not in use, you can simply add this to the constructor of the code behind:
this.DataContext = this;
Using this, every property in the code becomes accessible to binding:
<TextBlock Text="{Binding PropertyName}"/>
Another way is to just give a name to the root element of the XAML:
x:Name="root"
Since the XAML is compiled as a partial class of the code-behind, we can access every property by name:
<TextBlock Text="{Binding ElementName="root" Path=PropertyName}"/>
Note: access is only available to properties; not to fields. set; and get; or {Binding Mode = OneWay} are necessary. If OneWay binding is used, the underlying data should implement INotifyPropertyChanged.
For quick-and-dirty Windows in WPF, I prefer binding the DataContext of the Window to the window itself; this can all be done in XAML.
Window1.xaml
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource self}}"
Title="Window1" Height="300" Width="300">
<StackPanel>
<TextBlock Text="{Binding Path=MyProperty1}" />
<TextBlock Text="{Binding Path=MyProperty2}" />
<Button Content="Set Property Values" Click="Button_Click" />
</StackPanel>
</Window>
Window1.xaml.cs
public partial class Window1 : Window
{
public static readonly DependencyProperty MyProperty2Property =
DependencyProperty.Register("MyProperty2", typeof(string), typeof(Window1), new UIPropertyMetadata(string.Empty));
public static readonly DependencyProperty MyProperty1Property =
DependencyProperty.Register("MyProperty1", typeof(string), typeof(Window1), new UIPropertyMetadata(string.Empty));
public Window1()
{
InitializeComponent();
}
public string MyProperty1
{
get { return (string)GetValue(MyProperty1Property); }
set { SetValue(MyProperty1Property, value); }
}
public string MyProperty2
{
get { return (string)GetValue(MyProperty2Property); }
set { SetValue(MyProperty2Property, value); }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// Set MyProperty1 and 2
this.MyProperty1 = "Hello";
this.MyProperty2 = "World";
}
}
In the above example, note the binding used in the DataContext property on the Window, this says "Set your data context to yourself". The two text blocks are bound to MyProperty1 and MyProperty2, the event handler for the button will set these values, which will automatically propagate to the Text property of the two TextBlocks as the properties are Dependency Properties.
It is also worth noting that a 'Binding' can only be set on a DependencyProperty of a DependencyObject. If you want to set a non DependencyProperty (eg. a normal property) on an object in XAML, then you will have to use Robert's first method of using resources in the code behind.
myWindow.xaml
<Window
...
<TextBlock Text="{ Binding Path=testString }" />
</Window>
myWindow.xaml.cs
public partial class myWindow: Window
{
public string testString { get; set; } = "This is a test string";
public myWindow()
{
DataContext = this;
InitializeComponent();
}
}
Important
Set Datacontext
testString MUST be public
testString MUST be a property (have a get and set)