使用绑定的自定义附加属性

3
我在查看这个问题,但我不理解如何实际使用创建的AttachedProperty。问题是尝试在WebBrowser控件的源上进行绑定。

那里的代码看起来像:

public static class WebBrowserUtility
{
public static readonly DependencyProperty BindableSourceProperty =
    DependencyProperty.RegisterAttached("BindableSource", typeof(string), typeof(WebBrowserUtility), new UIPropertyMetadata(null, BindableSourcePropertyChanged));

public static string GetBindableSource(DependencyObject obj)
{
    return (string) obj.GetValue(BindableSourceProperty);
}

public static void SetBindableSource(DependencyObject obj, string value)
{
    obj.SetValue(BindableSourceProperty, value);
}

public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
    WebBrowser browser = o as WebBrowser;
    if (browser != null)
    {
            string uri = e.NewValue as string;
            browser.Source = uri != null ? new Uri(uri) : null;
    }
}
}

and

<WebBrowser ns:WebBrowserUtility.BindableSource="{Binding WebAddress}"
            ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
            ScrollViewer.VerticalScrollBarVisibility="Disabled" 
            Width="300"
            Height="200" />

WebAddress是什么?这是我的理解(可能是错误的):
  • There's an AttachedProperty that can be attached to any object, and in this particular case, it is basically just attaching a property called BindableSource which is of type String.
  • When we have the "{Binding WebAddress}" it means that in some c# code somewhere that handles this .xaml file there's something that looks like:

    public String WebAddress
    { 
        // get and set here? not sure
    }
    
  • And to take advantage of the property changed, I can called RaisedPropertyChanged and it will fire that static method up there?

即使我看了它,感觉不对,但我在网上找不到任何帮助。

1个回答

2
有一个AttachedProperty可以附加到任何对象上,在这种情况下,它基本上只是附加了一个名为BindableSource的属性,其类型为String。
你可能想阅读一下MSDN关于附加属性的文章
这相当简单:依赖属性使用字典,将控件与其属性值相关联,这使得添加诸如附加属性之类的东西变得非常容易,可以扩展控件。
在附加属性的RegisterAttached方法中,挂钩了一个PropertyChangedCallback,如果值发生更改,则会执行该回调。使用依赖属性使绑定成为可能,这也是首先这样做的原因。所有该属性真正做的就是在值更改时调用相关代码以导航浏览器。
当我们有"{Binding WebAddress}"时,这意味着在处理此.xaml文件的某个C#代码中,有些东西看起来像[...]。该绑定引用了WebBrowser的DataContext中名为WebAddress的公共属性或依赖属性(不是字段)。有关数据绑定的一般信息,请参见数据绑定概述。因此,如果您想创建一个应该是绑定源的属性,则可以实现INotifyPropertyChanged或创建DependencyProperty(它们会自行触发更改通知,通常仅在控件和UI相关类上创建这些属性)。您的属性可能如下所示:
public class MyModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    private string _webAddress;
    public string WebAddress
    {
        get { return _webAddress; }
        set
        {
            if (value != _webAddress)
            {
                _webAddress = value;
                NotifyPropertyChanged("WebAddress");
            }
        }
    }
}

在setter中你需要触发PropertyChanged事件,就像你所怀疑的那样。如何在XAML中声明有效的绑定是一个相当广泛的话题,因此我想再次引导你阅读前面提到的数据绑定概述,其中应该会解释清楚。
“为了利用属性更改,我可以调用RaisedPropertyChanged方法,然后它会触发上面的静态方法吗?”
事件被触发以触发绑定更新,这反过来又更改了附加属性的值,从而导致执行PropertyChangedCallback,最终导航到浏览器。

1
实际上,OP可能确实希望在实现WebAddress属性的ViewModel类中引发PropertyChanged事件。 - cordialgerm
@pickles:嗯,听起来很合理。 - H.B.
@pickles:我对我的答案进行了重大更新,希望现在能够解决所有的问题。 - H.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接