代码之家  ›  专栏  ›  技术社区  ›  Nick Gotch

将Silverlight自定义控件依赖项属性绑定到模型属性

  •  0
  • Nick Gotch  · 技术社区  · 15 年前

    我在Silverlight中有一个数据导航用户控件,它打开一个子窗口,用户可以在其中输入搜索条件,当他们按“应用”时,它将更新ViewModel(MVVM模式)中的绑定属性。

    链接为:搜索对话框<-->数据导航器<-->我的视图<-->我的视图模型

    SearchDialog中的Dependency属性似乎可以工作,当我设置其值时,它会显示在DataNavigator中;但是当Dependency属性更改时,似乎没有从DataNavigator向MyView/MyViewModel发送通知。

    SearchDialog从ChildWindow派生:

    public string Search
    {
     get { return (string)GetValue(SearchProperty); }
     set { SetValue(SearchProperty, value); }
    }
    
    public static readonly DependencyProperty SearchProperty =
     DependencyProperty.Register("Search", typeof(string), typeof(SearchDialog),
     new PropertyMetadata(null));
    

    数据导航器从用户控件派生:

    public Binding Search { get; set; }
    
    private void DataNavigator_Loaded(object sender, Windows.RoutedEventArgs e)
    {
     if (Search != null)
      this._searchDialog.SetBinding(SearchDialog.SearchProperty, Search);
    }
    

    myview从silverlightfx.userinterface.navigation.page派生:

    <DataNavigator MovePreviousAction="$model.MovePrevious()"
                   CurrentIndex="{Binding CurrentIndex, Mode=TwoWay}"
                   MoveNextAction="$model.MoveNext()"
                   SaveAction="$model.SaveChanges()"
                   IsLoading="{Binding IsLoading, Converter={StaticResource VisibilityConverter}}"
                   Search="{Binding SearchString, Mode=TwoWay}"/>
    

    MyViewModel从ViewModel派生:

    public string SearchString
        {
         get { return this._search; }
    
      set
      {
       if(value != this._search)
       {
        this._search = value;
        this.RaisePropertyChanged("SearchString");
       }
      }
     }
    

    我花了好几个小时试图找出问题所在,但没有取得任何成功;有人看到这个问题吗?事先谢谢,

    2 回复  |  直到 14 年前
        1
  •  1
  •   Bryant    15 年前

    不确定中间的绑定属性是否有效,因为您正试图将其绑定到string类型的属性。

    既然你已经在用尼基的东西了,你可能想看看 how he uses Tasks to handle dialogs/child windows 同时保持MVVM范式的位置。

        2
  •  0
  •   Community CDub    7 年前

    Bryant's solution 看起来不错,但我还是有些问题。我最终使用了以下方法使其工作:

    我在SearchDialog中添加了一个事件,当搜索模式dp更改时将触发该事件:

    public string Search
    {
        get { return (string)GetValue(SearchProperty); }
        set { SetValue(SearchProperty, value); }
    }
    
    public static readonly DependencyProperty SearchProperty =
        DependencyProperty.Register("Search", typeof(string), typeof(SearchDialog),
        new PropertyMetadata(null, new PropertyChangedCallback(OnSearchChanged)));
    
    private static void OnSearchChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // call to instance method
        ((SearchDialog)d).OnSearchChanged(e);
    }
    
    protected virtual void OnSearchChanged(DependencyPropertyChangedEventArgs e)
    {
        if (SearchChanged != null)
            this.SearchChanged(this, e);
    }
    
    public event DependencyPropertyChangedEventHandler SearchChanged;
    

    在此之后,我在数据导航器中添加了另一个DP:

    public string Search
    {
        get { return (string)GetValue(SearchProperty); }
        set { SetValue(SearchProperty, value); }
    }
    
    public static readonly Windows.DependencyProperty SearchProperty =
    Windows.DependencyProperty.Register("Search", typeof(string), typeof(DataNavigator),
    new Windows.PropertyMetadata(null));
    

    然后将导航器的DP连接到SearchDialog的DP,以便将对搜索属性的更改传播到数据导航器,然后将数据导航器绑定到V&VM。

    // Inside the Loaded Event:
    this._searchDialog.SearchChanged +=
        new System.Windows.DependencyPropertyChangedEventHandler(Search_Changed);
    
    // Handler:
    private void Search_Changed(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        string search = this._searchDialog.GetValue(SearchDialog.SearchProperty) as string;
        this.Search = search != null ? search.ToString() : null;
    }
    

    其余的事情和上面一样,我得到了我想要的效果。