Creating a proxy for a dependency property

I am trying to create a simple proxy resource for dependency properties. I created my own control, it is a file collector, which is made from a text field (name: "TextBox_FilePath" ) and a button that opens a dialog box for an open file.

Since I'm doing reuse, I would like it to have the "SelectedFilePath" property. Since the Text property seems ideal for my control as a "SelectedFilePath" property, I just would like to proxy this dependency property.

The first approach I did was the following:

 public static readonly DependencyProperty SelectedFilePathProperty = TextBox.TextProperty; public string SelectedFilePath { get { return (string) this.TextBox_FilePath.GetValue(SelectedFilePathProperty); } set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); } } 

which worked, but threw an exception when trying to bind to this property. Then I worked:

 public static readonly DependencyProperty SelectedFilePathProperty = DependencyProperty.Register("SelectedFilePath", typeof (string), typeof (FilePicker), new PropertyMetadata(default(string))); public string SelectedFilePath { get { return (string) this.TextBox_FilePath.GetValue(SelectedFilePathProperty); } set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); } } 

which works, but I have no idea why ?! Where have I pointed out, do I need the Text property of a text field?

What am I missing just to proxy this dependency property?

EDIT: The AddOwner doesn’t work either, it throws an Excetion saying that "the binding can only be applied to the dependency property." The code:

 public static readonly DependencyProperty SelectedFilePathProperty = TextBox.TextProperty.AddOwner(typeof(FilePicker)); public string SelectedFilePath { get { return (string)this.TextBox_FilePath.GetValue(SelectedFilePathProperty); } set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); } } 

What? I do not understand?

EDIT2: For everyone who has trouble understanding the answer, I made a little graphics

+6
source share
3 answers

The first approach does not work, because the property is registered only for TextBox , adding a link to another class does nothing.

The second only creates a new string property.

If you really want to reuse the TextBox.TextProperty AddOwner on it.

eg.

 public static readonly DependencyProperty SelectedFilePathProperty = TextBox.TextProperty.AddOwner(typeof(FilePicker)); 

(Note that this property is registered as "Text" so you should probably just create a new property with the name you want, like you. I would also recommend setting the metadata flags to bind two-way by default , if you want have the same binding behavior as TextBox.Text .)

+3
source

This solution is a bit complicated, but it works.

Given this user control:

 <Grid> <StackPanel> <WpfApplication1:FilePicker SelectedFilePath ="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <TextBlock Text="{Binding MyProperty}" /> </StackPanel> </Grid> 

And its viewmodel:

 public class MainWindowViewModel : INotifyPropertyChanged { #region Implementation of INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string e) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(e)); } #endregion private string _myProperty; public string MyProperty { get { return _myProperty; } set { _myProperty = value; OnPropertyChanged("MyProperty"); } } } 

XAML for managing FilePicker:

 <Grid> <TextBox x:Name="TextBox_FilePath" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type WpfApplication1:FilePicker}}}" Text="{Binding SelectedFilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </Grid> 

CodeBehind for managing FilePicker:

 public partial class FilePicker : UserControl { public FilePicker() { InitializeComponent(); } /* private PROXY DP*/ private static readonly DependencyProperty TextProperty = TextBox.TextProperty.AddOwner(typeof(FilePicker)); /* public DP that will fire getter/setter for private DP */ public static readonly DependencyProperty SelectedFilePathProperty = DependencyProperty.Register("SelectedFilePath", typeof(string), typeof(FilePicker), new PropertyMetadata(default(string))); public string SelectedFilePath { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } } 

It works like a charm.

+1
source

How I understood the problems. HBs answer I made a short schedule that helped me understand what was going on under the hood. Here it is:

enter image description here

Maybe this helps someone else :)

0
source

Source: https://habr.com/ru/post/917809/


All Articles