为依赖项属性创建代理

时间:2012-06-11 15:01:41

标签: c# wpf xaml proxy dependency-properties

我正在尝试创建一个简单的依赖属性代理。我制作了一个自定义控件,它是一个文件选择器,由一个文本框(名称:"TextBox_FilePath")和一个显示打开文件对话框的按钮组成。

当我进行可重复使用的控件时,我希望它具有"SelectedFilePath"属性。由于Text属性似乎非常适合我的控件成为"SelectedFilePath"属性,我只想代理这些依赖属性。

我做的第一个方法是:

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); }
}

有效,但在尝试绑定到该属性时抛出异常。然后我走了:

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); }
}

哪个确实有用,但我不明白为什么?!我在哪里指定了我想要文本框的text属性?

简单地代理该依赖属性我缺少什么?

修改 使用AddOwner的解决方案也不起作用,它抛出一个Excetion,说“绑定只能应用于依赖属性”。代码:

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); }
}

我不明白什么?

EDIT2: 对于其他有问题理解答案的人,我做了a little graphic

3 个答案:

答案 0 :(得分:2)

第一种方法不起作用,因为该属性仅为TextBox 注册,在另一个类中添加引用不起任何作用。

第二个只是创建一个全新的字符串属性。

如果您真的想在其上重复使用TextBox.TextProperty来电AddOwner

e.g。

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

(请注意,此属性已注册为"Text",因此您可能应该只创建一个具有所需名称的新属性。我还建议set metadata flags到{{3如果你想拥有与TextBox.Text相同的绑定行为。)

答案 1 :(得分:1)

这个解决方案有点棘手但有效。

鉴于此用户控制:

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

它的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");
        }
    }
}

FilePicker控件的XAML:

<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>

CodePehind for 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); }
    }
}

像魅力一样。

答案 2 :(得分:0)

因为我在理解H.B.s answer时遇到了问题,所以我制作了一个图形,帮助我理解了幕后发生的事情。这是;

enter image description here

也许它可以帮助别人:)