DependencyProperty for TextBox gives compile time error (UWP) - c#

I have a textbox with a DependencyProperty, Code looks like this
<UserControl
x:Class="Projectname.Controls.Editors.EditTextControl"
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:ui="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
mc:Ignorable="d">
<Grid>
<TextBox PlaceholderText="I'am Active" HasError="{Binding IsInvalid, UpdateSourceTrigger=PropertyChanged}" Height="80" Width="300" x:Name="txtActive" Text="{Binding TextValue, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" ></TextBox>
</Grid>
public sealed partial class EditTextControl : UserControl
{
TestViewModel TV = new TestViewModel();
public EditTextControl()
{
this.InitializeComponent();
this.DataContext = TV;
}
public bool HasError
{
get { return (bool)GetValue(HasErrorProperty); }
set { SetValue(HasErrorProperty, value); }
}
/// <summary>
/// This is a dependency property that will indicate if there's an error.
/// This DP can be bound to a property of the VM.
/// </summary>
public static readonly DependencyProperty HasErrorProperty =
DependencyProperty.Register("HasError", typeof(bool), typeof(EditTextControl), new PropertyMetadata(false, HasErrorUpdated));
// This method will update the Validation visual state which will be defined later in the Style
private static void HasErrorUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EditTextControl textBox = d as EditTextControl;
if (textBox != null)
{
if (textBox.HasError)
VisualStateManager.GoToState(textBox, "InvalidState", false);
else
VisualStateManager.GoToState(textBox, "ValidState", false);
}
}
}
All looks good to me, But on compile-time itself, it's giving these errors.
The property 'HasError' was not found in type 'TextBox'.
The member "HasError" is not recognized or is not accessible.
Can anyone please point out what I am doing wrong here?

HasError is a property on the EditTextControl user control, not on the TextBox.
If you want to add a custom property to the TextBox class, you use an Attached Property not a Dependency property.

Related

FlipView Datatemplate fails to bind on custom UserControl

TL;DR
Using MahApps' FlipView with a custom DataTemplate, binding fails to update when using a custom UserControl.
Issue
Trying to use MahApps's FlipView to host a custom UserControl for each view. For testing purposes, my UserControl looks like this (testing this on MetroDemo sample project)
XAML
<UserControl x:Class="MetroDemo.ExampleViews.CustomImageControl"
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:MetroDemo.ExampleViews"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid x:Name="ControlContainer">
<Image Source="{Binding SourceImage}" Stretch="Fill"/>
</Grid>
</UserControl>
Code Behind
namespace MetroDemo.ExampleViews
{
/// <summary>
/// Interaction logic for CustomImageControl.xaml
/// </summary>
public partial class CustomImageControl : UserControl
{
public ImageSource SourceImage
{
get => (ImageSource)this.GetValue(SourceImageProperty);
set
{
this.SetValue(SourceImageProperty, value);
}
}
public static readonly DependencyProperty SourceImageProperty = DependencyProperty.Register(
nameof(SourceImage),
typeof(ImageSource),
typeof(CustomImageControl),
new PropertyMetadata(OnSourceImageChanged));
private static void OnSourceImageChanged(DependencyObject data, DependencyPropertyChangedEventArgs args)
{
var control = (CustomImageControl)data;
if (control is null || !(args.NewValue is ImageSource image))
return;
control.SourceImage = image;
}
public CustomImageControl()
{
InitializeComponent();
this.ControlContainer.DataContext = this;
}
}
}
Then, I'm using this custom user control within a DataTemplate that FlipView uses, replacing this bit here for:
<DataTemplate x:Key="ImageDataTemplate" x:Shared="False">
<local:CustomImageControl SourceImage="{Binding Mode=OneWay, FallbackValue={x:Static DependencyProperty.UnsetValue}, Converter={mah:NullToUnsetValueConverter}}" />
</DataTemplate>
When flipping to the next view, it animates but for some reason it keeps the same first bound image.
It seems that the binding is failing somewhere but I can't see where. Any help is highly appreciated!
if I comment out the following it works like expected:
private static void OnSourceImageChanged(DependencyObject data, DependencyPropertyChangedEventArgs args)
{
//var control = (CustomImageControl)data;
//if (control is null || !(args.NewValue is ImageSource image))
// return;
//control.SourceImage = image;
}
it basically gets a new value and sets it as a new ImageSource which will call the OnSourceImageChanged. In this void it sets a new ImageSource which will call this OnSourceImageChanged again.

How To Prevent Constructor from being called on value change

I have a custom usercontrol that I'm using in a DataTemplate. In this usercontrol I have a text box. Previously when I was implementing this usercontrol I would have no problems but now that I've put it into a Datatemplate it seems that something has gone wrong.
Each time I type something into the text box the code runs normally but at the end of my triggers the usercontrols constructor gets called again and clears my textbox. (Hidden threads call it so I have no idea where to even start looking for where this unintuitive call originates from)
I'm trying to figure out what is causing this constructor to fire again. The other binds seem to work well and the correct information is being populated and displayed. It's just that constructor that is called again after everything resolves and clears the internal variables of the ui control.
Current Execution:
I type into the textbox. The triggers get my value of the text box filters the lists accordingly and than the constructor gets called and the textbox resets to default value of "".
Desired Execution:
I type into the textbox. The triggers get my value of the text box filters the lists accordingly.
<UserControl x:Class="Analytics_Module.Views.TenantProfileFilterFieldsView"
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:Analytics_Module.Views"
xmlns:vm="clr-namespace:Analytics_Module.ViewModels"
xmlns:uiComponents="clr-namespace:Analytics_Module.UI_Components"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<DockPanel>
<DockPanel.DataContext>
<vm:TenantProfileFilterFieldsViewModel x:Name="test"/>
</DockPanel.DataContext>
....
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding FiltersState.GroupedTenantNames, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<uiComponents:neoCombobox
LabelText="Tenant Names"
ListBoxItems="{Binding StaticLists.TenantNames, ElementName=test}"
DisplayListBoxItems ="{Binding}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
CUSTOM USER CONTROL
<UserControl x:Class="Analytics_Module.UI_Components.neoCombobox"
x:Name="parent"
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:model="clr-namespace:Analytics_Module.Models"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<StackPanel DataContext="{Binding ElementName=parent}" Width="200">
<Label Name="ComboboxLabel"
Content="{Binding Path=LabelText, FallbackValue='Error'}" Margin="5"/>
<TextBox Name="InputField"
Text="{Binding Path=TextBoxValue, Mode=TwoWay, FallbackValue='Error', UpdateSourceTrigger='PropertyChanged'}"/>
<!--TODO rename -->
<ListBox Name="Something"
ItemsSource="{Binding Path=DisplayListBoxItems, FallbackValue={}, Mode=TwoWay}" >
<ListBox.ItemTemplate >
<DataTemplate >
<StackPanel>
<CheckBox Margin="-1"
Content="{Binding Name, FallbackValue='Error'}"
IsChecked="{Binding Check_Status, Mode=TwoWay, FallbackValue=true}">
</CheckBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</UserControl>
Back end of user contorl
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Analytics_Module.Models;
using Analytics_Module.Utillity;
using System.Timers;
using System.Collections.Specialized;
namespace Analytics_Module.UI_Components
{
/// <summary>
/// Interaction logic for neoCombobox.xaml
/// </summary>
public partial class neoCombobox : UserControl
{
#region LabelText DP
public String LabelText
{
get { return (String)GetValue(LabelTextProperty); }
set { SetValue(LabelTextProperty, value); }
}
public static readonly DependencyProperty LabelTextProperty =
DependencyProperty.Register("LabelText",
typeof(string),
typeof(neoCombobox), new PropertyMetadata("")
);
#endregion
#region TextBoxValue DP
/// <summary>
/// Gets or sets the Value which is being displayed
/// </summary>
public String TextBoxValue
{
get { return (String)GetValue(TextBoxValueProperty); }
set { SetValue(TextBoxValueProperty, value); }
}
/// <summary>
/// Identified the TextBoxValue dependency property
/// </summary>
public static readonly DependencyProperty TextBoxValueProperty =
DependencyProperty.Register("TextBoxValue",
typeof(String),
typeof(neoCombobox),
new PropertyMetadata("")
);
#endregion
#region ListBoxItems DP
public ItemsChangeObservableCollection<MultiSelectDropDownListEntry> ListBoxItems
{
get { return (ItemsChangeObservableCollection<MultiSelectDropDownListEntry>)GetValue(ListBoxItemsProperty); }
set { SetValue(ListBoxItemsProperty, value); }
}
public static readonly DependencyProperty ListBoxItemsProperty =
DependencyProperty.Register("ListBoxItems",
typeof(ItemsChangeObservableCollection<MultiSelectDropDownListEntry>),
typeof(neoCombobox),
new PropertyMetadata(new ItemsChangeObservableCollection<MultiSelectDropDownListEntry>())
);
#endregion
#region DisplayListBoxItems DP
public ItemsChangeObservableCollection<MultiSelectDropDownListEntry> DisplayListBoxItems
{
get {
if (GetValue(DisplayListBoxItemsProperty) == null)
{
SetValue(DisplayListBoxItemsProperty, new ItemsChangeObservableCollection<MultiSelectDropDownListEntry>());
}
return (ItemsChangeObservableCollection<MultiSelectDropDownListEntry>)GetValue(DisplayListBoxItemsProperty);
}
set { SetValue(DisplayListBoxItemsProperty, value); }
}
public static readonly DependencyProperty DisplayListBoxItemsProperty =
DependencyProperty.Register("DisplayListBoxItems",
typeof(ItemsChangeObservableCollection<MultiSelectDropDownListEntry>),
typeof(neoCombobox),
new PropertyMetadata(new ItemsChangeObservableCollection<MultiSelectDropDownListEntry>())
);
#endregion
/// <summary>
/// _timer is used to determine if a user has stopped typing.
/// The timer is started when a user starts typing again or
/// types for the first time.
/// </summary>
private readonly Timer _timerKeyPress;
/// <summary>
/// _timer is used to determine if a user has left the typing.
/// The timer is started when a user starts typing again or
/// types for the first time.
/// </summary>
private readonly Timer _timerMouseLeave;
public neoCombobox()
{
if (TextBoxValue != "") return;
InitializeComponent();
_timerKeyPress = new Timer();
_timerKeyPress.Interval = 750;
_timerKeyPress.Elapsed += new ElapsedEventHandler(UserPausedTyping);
_timerKeyPress.AutoReset = false;
_timerMouseLeave = new Timer();
_timerMouseLeave.Interval = 550;
//_timerMouseLeave.Elapsed += new ElapsedEventHandler(UserLeft);
_timerMouseLeave.AutoReset = false;
}
//TODO Add property to determine if user preferes Mouse Leave of focus leave.
protected override void OnPreviewGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
Console.WriteLine("###############OnPreviewGotKeyboardFocus");
_timerMouseLeave.Stop();
base.OnPreviewGotKeyboardFocus(e);
}
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
Console.WriteLine("------------OnPreviewLostKeyboardFocus");
_timerMouseLeave.Stop();
_timerMouseLeave.Start();
base.OnPreviewLostKeyboardFocus(e);
}
protected override void OnMouseEnter(MouseEventArgs e)
{
_timerMouseLeave.Stop();
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(MouseEventArgs e)
{
_timerMouseLeave.Stop();
_timerMouseLeave.Start();
base.OnMouseLeave(e);
}
protected override void OnKeyUp(KeyEventArgs e)
{
_timerKeyPress.Stop();
_timerKeyPress.Start();
}
private void UserPausedTyping(object source, ElapsedEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
Console.WriteLine("###############UserPausedTyping");
this.RefreshDisplayList();
});
}
private void UserLeft(object source, ElapsedEventArgs e)
{
this.Dispatcher.Invoke(() =>
{
Console.WriteLine("###############User Left");
this.TextBoxValue = "";
this.RefreshDisplayList();
});
}
protected void RefreshDisplayList()
{
int ItemsourceCount = 0;
foreach (MultiSelectDropDownListEntry entry in this.DisplayListBoxItems.ToList())
{
if (!entry.Check_Status) this.DisplayListBoxItems.Remove(entry);
}
if (this.TextBoxValue == "") return;
foreach (MultiSelectDropDownListEntry entry in this.ListBoxItems)
{
if (entry.Name.ToString().ToLower().Contains(this.TextBoxValue.ToLower()) && !this.DisplayListBoxItems.Contains(entry))
{
this.DisplayListBoxItems.Add(entry);
if (ItemsourceCount++ > 15) break;
}
}
}
}
}
You cannot always avoid the recreation of containers by the ItemsControl, but you can make your text data persistent by binding the Text property of your TextBox to a property of the view model and not to a property of the custom control itself.
Instead of writing:
<TextBox Name="InputField" Text="{Binding Path=TextBoxValue, Mode=TwoWay, FallbackValue='Error', UpdateSourceTrigger='PropertyChanged'}"/>
maybe write
<TextBox Name="InputField" Text="{Binding MyTextProperty, Mode=TwoWay, FallbackValue='Error', UpdateSourceTrigger='PropertyChanged'}"/>
and have the MyTextProperty defined in your view model like this:
public class GroupedTenantNameViewModel {
public string MyTextProperty { get; set; }
}
and make your FiltersState.GroupedTenantNames collection a collection of GroupedTenantNameViewModel items. This collection will be persistent even though the ItemsControl re-generates all items, and the binding will take care of putting data back in its place.
If you're not using the MVVM pattern at all, then I suggest you research a bit into it as it's made to deal with bindings the right way!

How to tie together custom dependency properties of UserControl with properties of nested controls?

I have a UserControl that includes three TextBlock controls. I want to implement three custom properties in UserControl. Something like:
public partial class MyControl: UserControl
{
...
public String Title
{
get { return this.textBlock1.Text; }
set { this.textBlock1.Text = value; }
}
public String Units
{
get { return this.textBlock2.Text; }
set { this.textBlock2.Text = value; }
}
public String Data
{
get { return this.textBlock3.Text; }
set { this.textBlock3.Text = value; }
}
}
If I want to use binding capabilities with these properties I have to implement them as dependency properties. Am I right? But I do not know how to do it in my case.
That is correct. Binding to dependency properties is quite simple to do. Understanding the mechanics I would suggest looking through MSDN. However to answer your question you provide static dependency properties registered to the user control. Then your getters \ setters reference the property.
Here is a sample line of a dependency property.
/// <summary>
/// Provides a bindable text property to the user control
/// </summary>
public static DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(UserControl1), new PropertyMetadata("", onTextPropertyChanged));
/// <summary>
/// optional static call back handler when the property changed
/// </summary>
/// <param name="o"></param>
/// <param name="e"></param>
static void onTextPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var obj = o as UserControl1;
if (obj == null)
return;
//TODO: Changed...
}
/// <summary>
/// Gets \ sets the text
/// </summary>
public string Text
{
get { return (string)this.GetValue(TextProperty); }
set
{
if (this.Text != value)
this.SetValue(TextProperty, value);
}
}
The above is very simple. We register a dependency property TextProperty to UserControl1, this property is the type of string and has a default value of "" (as noted in the property meta data). I also provided a static callback handler if you wish to perform additional steps once the property has changed.
You will then see the Text property uses the GetValue() and SetValue() methods for getting and setting the value of the Text Property.
UPDATE: Binding to a child element in XAML.
This update is to show how to use the the above TextProperty for binding.
Usercontrol1.Xaml. This is the XAML for UserControl1.
<UserControl x:Class="WpfApplication1.UserControl1"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" FontWeight="Bold" Content="Text" VerticalAlignment="Center" />
<TextBox Text="{Binding Text, Mode=TwoWay}" Grid.Column="1" VerticalAlignment="Center" Padding="4" />
</Grid>
</UserControl>
My Main Window View Model (Implement INotifyPropertyChanged)
public class MainWindowModel : INotifyPropertyChanged
{
/// <summary>
/// the text
/// </summary>
string myProperty = "This is the default text";
/// <summary>
/// Gets \ sets the text
/// </summary>
public string MyProperty
{
get { return this.myProperty; }
set
{
if (this.MyProperty != value)
{
this.myProperty = value;
this.OnPropertyChanged("MyProperty");
}
}
}
/// <summary>
/// fires the property changed event
/// </summary>
/// <param name="propertyName"></param>
private void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// the property changed event
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
}
MainWindow.Xaml. Binding the text property to the view model
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:WpfApplication1"
Name="Window1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<ctrl:MainWindowModel />
</Window.DataContext>
<Grid>
<ctrl:UserControl1 Text="{Binding Path=DataContext.MyProperty, Mode=TwoWay, ElementName=Window1}" />
</Grid>
</Window>
Code for the dependency property :
public string Title
{
get { return (string)this.GetValue(TitleProperty); }
set { this.SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title",
typeof(string),
typeof(MyControl),
new PropertyMetadata(null));
Binding in xaml :
<TextBlock Text="{Binding Title,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type yourXmlns:MyControl}}"/>

Binding to DependencyProperty works only with "MyValue" and not "{Binding PropertyHoldingMyValue}"

I am creating a custom "PageHeaderControl" UserControl, with a header property:
public partial class PageHeaderControl: UserControl
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header",
typeof(string), typeof(PageHeaderControl),
new PropertyMetadata(""));
public string Header
{
get { return GetValue(HeaderProperty) as string; }
set { SetValue(HeaderProperty, value); }
}
}
In the XAML for that control, I have:
<sdk:Label Content="{Binding Header,Mode=TwoWay}" />
Now for the problem: When I create the control, binding it only works to do this:
<my:PageHeaderControl Header="This is my page header" />
And it does not work to do this, where PageHeader is the property in my ViewModel holding the header value:
<my:PageHeaderControl Header="{Binding PageHeader,Mode=TwoWay}" />
I thought maybe my properties were messed up, but this also works:
<TextBlock Text="{Binding PageHeader,Mode=TwoWay}" />
Any ideas as to what the problem could be!
Thanks so much!!!
Edit:
In my ViewModel, PageHeader is this:
private string _pageHeader = "This is my page header";
public string PageHeader
{
get
{
return _pageHeader;
}
set
{
_pageHeader = value;
RaisePropertyChanged("PageHeader");
}
}
Edit 2:
When I put a breakpoint inside the "get" for my PageHeader property, it does not get hit AT ALL, unless I add in the TextBlock...
If I understand you correctly you're trying to bind a property of an element within your control's XAML markup to the property of the control itself.
If this is the case, see if the following helps you.
PageHeaderControl.xaml:
<UserControl x:Class="TryElementBinding.PageHeaderControl"
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"
x:Name = "MyControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding Header, ElementName=MyControl}"></TextBlock>
</Grid>
PageHeaderControl.xaml.cs:
public partial class PageHeaderControl : UserControl
{
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(PageHeaderControl), new PropertyMetadata(""));
public string Header
{
get
{
return GetValue(HeaderProperty) as string;
}
set
{
SetValue(HeaderProperty, value);
}
}
public PageHeaderControl()
{
InitializeComponent();
}
}
ViewModel.cs:
public class ViewModel : INotifyPropertyChanged
{
private string _pageHeader = "This is my page header";
public string PageHeader
{
get
{
return _pageHeader;
}
set
{
_pageHeader = value;
PropertyChanged(this, new PropertyChangedEventArgs("PageHeader"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
MainPage.xaml:
<Grid x:Name="LayoutRoot" Background="White">
<my:PageHeaderControl Header="{Binding PageHeader, Mode=TwoWay}"></my:PageHeaderControl>
</Grid>
MainPage.xaml.cs:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
I'm a little bit confused and I think you missed the syntax of Binding inline expression.
after "{Binding" comes Path to your property. Is "PageHeader" is a path to your property?!
I think you mean this:
<my:PageHeader Header="{Binding PageHeader, Mode=TwoWay}" />
<TextBlock Text="{Binding PageHeader, Mode=TwoWay}" />
The problem is that Binding expression only works when you set the value of property using SetValue method and notify the parent DependencyObject that specific property has changed!
You should use a DependencyProperty to have TwoWay Binding on it, OR implement System.ComponentModel.INotifyPropertyChange interface in your class and notify the Binding object manually by calling PropertyChanged event in the interface.
The definition of PageHeader property should be like this:
public static readonly DependencyProperty PageHeaderProperty = DependencyProperty.Register("PageHeader", typeof(string), typeof(YOUROWNER), new PropertyMetadata(""));
public string PageHeader
{
get { return GetValue(PageHeaderProperty) as string; }
set { SetValue(PageHeaderProperty, value); }
}
Cheers

Simple Dependency Property and UserControl issues in C#

My end goal is to expose the Text value of a TextBox that I have in a UserControl, from the UserControl's call in XAML.
<my:UserControl SetCustomText="Blah blah this is variable">
would render the UserControl with that TextBox's text filed in.
I've been working at it using various examples but I always end up with "The Property SetCustomText was not found in type UserControl"
Example of how you can do this:
<UserControl x:Class="Test.UserControls.MyUserControl1"
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"
Name="control">
<Grid>
<!-- Text is being bound to outward representative property -->
<TextBox Text="{Binding MyTextProperty, ElementName=control}"/>
</Grid>
</UserControl>
public partial class MyUserControl1 : UserControl
{
// The dependency property which will be accessible on the UserControl
public static readonly DependencyProperty MyTextPropertyProperty =
DependencyProperty.Register("MyTextProperty", typeof(string), typeof(MyUserControl1), new UIPropertyMetadata(String.Empty));
public string MyTextProperty
{
get { return (string)GetValue(MyTextPropertyProperty); }
set { SetValue(MyTextPropertyProperty, value); }
}
public MyUserControl1()
{
InitializeComponent();
}
}
<uc:MyUserControl1 MyTextProperty="Text goes here"/>

Categories