Проблема с привязкой свойства зависимости пользовательского элемента управления Silverlight к свойству модели

У меня есть пользовательский элемент управления для навигации по данным в Silverlight, который открывает дочернее окно, в котором пользователь может ввести критерии поиска, и когда они нажимают «Применить», предполагается, что необходимо обновить связанное свойство в ViewModel (шаблон MVVM).

Ссылки: SearchDialog ‹--> DataNavigator ‹--> MyView ‹--> MyViewModel

Свойство зависимости в SearchDialog, кажется, работает, когда я устанавливаю его значение, оно отображается в DataNavigator; однако, когда свойство зависимости изменяется, кажется, что никакое уведомление не отправляется из 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));

DataNavigator является производным от UserControl:

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

Я часами пытался найти проблему, но безуспешно; кто-нибудь видит проблему? Заранее спасибо,


person Nick Gotch    schedule 12.11.2009    source источник
comment
XAML для моего представления - это DataNavigator? Это представление или DataNavigator в представлении? Я также не вижу никакой связи между свойством SearchString в вашей виртуальной машине и привязкой поиска в представлении (или это DataNavigator?).   -  person Bryant    schedule 12.11.2009
comment
@Bryant Я вырезал из MyView только часть ‹DataNavigator .. /›, остальное я могу опубликовать, но это не имеет отношения к вопросу. Параметр поиска DataNavigator (я полагаю) привязан к SearchString в виртуальной машине и (опять же, я считаю) привязан к свойству зависимости из SearchDialog. Я могу что-то здесь сбить с толку (новинка для DP), поэтому, если да, предложите изменение, которое я мог бы внести.   -  person Nick Gotch    schedule 13.11.2009
comment
Хорошо, теперь я это вижу. Не уверен, что это сработает, поскольку вы привязываете строку к Binding. Я бы подумал, что свойство поиска должно быть строкой, чтобы эта привязка работала.   -  person Bryant    schedule 13.11.2009


Ответы (2)


Не уверен, что это свойство Binding посередине будет работать, поскольку вы пытаетесь привязать его к свойству типа string.

Поскольку вы уже пользуетесь некоторыми вещами Nikhil, возможно, вам стоит взглянуть на как он использует Задачи для обработки диалогов / дочерних окон, сохраняя при этом парадигму MVVM.

person Bryant    schedule 12.11.2009

решение Брайанта выглядит так: правильный путь, но у меня все еще были проблемы. В итоге я заставил это работать, используя следующий подход:

Я добавил событие в 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 в DataNavigator:

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 Navigator к DP SearchDialog, чтобы изменения свойства Search распространялись на DataNavigator, который затем привязывается к 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;
}

Остальное остается таким же, как указано выше, и я получаю желаемый эффект.

person Nick Gotch    schedule 13.11.2009