Привязка данных Silverlight к свойствам родительского пользовательского элемента управления с использованием MVVM в обоих элементах управления - PullRequest
0 голосов
/ 17 мая 2010

У меня есть два элемента UserControl («UserControlParentView» и «UserControlChildView») с шаблоном MVVM, реализованным в обоих элементах управления. Родительский элемент управления является контейнером для дочернего элемента управления, и свойство дочернего элемента управления должно обновляться привязкой данных из родительского элемента управления, чтобы отображать / скрывать некоторые флажки внутри дочернего элемента управления.

Описание родительского контроля

UserControlParentViewModel имеет свойство:

    private bool isShowCheckbox = false;
    public bool IsShowCheckbox
    {
        get { return isShowCheckbox; }
        set { isShowCheckbox = value; NotifyPropertyChanged("IsShowCheckbox");  }
    }

UserControlParentViewModel - как установить DataContext родительского элемента управления:

    public UserControlParentView()
    {
        InitializeComponent();

        this.DataContext = new UserControlParentViewModel();
    }        

UserControlParentView содержит кнопку-переключатель (в XAML), связанную со свойством UserControlParentViewModel IsShowCheckbox

<ToggleButton Grid.Column="1" IsChecked="{Binding IsShowCheckbox, Mode=TwoWay}"></ToggleButton>

Также родительский элемент управления содержит экземпляр дочернего элемента (где-то в XAML)

<local:UserControlChildView IsCheckBoxVisible="{Binding IsShowCheckbox}" ></local:UserControlChildView>

, поэтому свойство в дочернем элементе управления должно обновляться, когда пользователь переключает / снимает кнопку. Дочерний элемент управления содержит логическое свойство, которое необходимо обновить из родительского элемента управления, но ничего не произошло! Точка останова никогда не срабатывает!

Свойство в UserControlChildView, которое следует обновить из родительского элемента управления (здесь я планирую сделать видимым / скрытым chechBox в коде позади):

    public bool IsCheckBoxVisible
    {
        get { return (bool)GetValue(IsCheckBoxVisibleProperty); }
        set { SetValue(IsCheckBoxVisibleProperty, value); }
    }
    // Using a DependencyProperty as the backing store for IsCheckBoxVisible.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsCheckBoxVisibleProperty =
        DependencyProperty.Register("IsCheckBoxVisible", typeof(bool), typeof(TopMenuButton), new PropertyMetadata(false));

Так вот вопрос - что я делаю не так? Почему собственность ребенка никогда не обновляется? Кстати, в окне вывода нет сообщений об ошибках привязки ...

Ответы [ 5 ]

2 голосов
/ 17 мая 2010

Вы не указываете, где вы поставили точку останова «никогда не срабатывает!». Я предполагаю, что вы устанавливаете точку останова в методе мутации set свойства IsCheckBoxVisible.

Вы работаете в предположении, что привязка этого свойства в какой-то момент приведет к вызову метода set при присвоении значения. Однако платформа связывания Silverlight фактически вызывает SetValue напрямую. Он передает методу SetValue значение IsCheckBoxVisibleProperty и назначаемое значение.

0 голосов
/ 17 мая 2010

Хорошо, похоже, все работало нормально, и меня смутила просто точка останова без запуска.

Для простоты я решил удалить IsCheckBoxVisible boolean depen.property из дочернего элемента управления и привязать видимость checkBox в дочернем элементе управления непосредственно к CheckBoxVisibility depen.property (тип - Visibility).

Также в родительском контроле теперь у меня есть это:

<local:UserControlChildView CheckBoxVisibility="{Binding Path=CheckboxControlVisibility}"></local:UserControlChildView>

Итак, теперь в родительском элементе управления есть свойство CheckboxControlVisibility (тип - Visibility)

0 голосов
/ 17 мая 2010

Я почти уверен, что вы не можете привязать свойство зависимостей к пользовательскому элементу управления в Silverlight 3. Я сам попробовал его 9 месяцев назад и пытался заставить его работать. В конце концов я где-то читал, что это просто невозможно. Я сделал это в WPF, поэтому какое-то время бился об этом, думая, что это моя реализация.

Итак, на первый взгляд ваш код выглядит правильно, но это не поможет.

Я думал, что это было исправлено в SL4.

Используете ли вы SL4?

0 голосов
/ 17 мая 2010

Хохо !! У меня это работает!

В дочернем контроле я немного изменил свойство

    public bool IsCheckBoxVisible
    {
        get { return (bool)GetValue(IsCheckBoxVisibleProperty); }
        set { SetValue(IsCheckBoxVisibleProperty, value); }
    }
    // Using a DependencyProperty as the backing store for IsCheckBoxVisible.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IsCheckBoxVisibleProperty =
        DependencyProperty.Register("IsCheckBoxVisible", typeof(bool), typeof(UserControlChildView), new PropertyMetadata(false, new PropertyChangedCallback((d, dc) => 
        {
            var button = d as UserControlChildView;
            button.CheckBoxVisibility = ((bool)dc.NewValue) ? Visibility.Visible : Visibility.Collapsed;
        })));

так что теперь у меня есть новая подписка на события (см. Анонимный метод), и она срабатывает, когда в родительском контроле свойство IsShowCheckbox изменяется!

CheckBoxVisibility depen.property выглядит так:

    public Visibility CheckBoxVisibility
    {
        get { return (Visibility)GetValue(CheckBoxVisibilityProperty); }
        set { SetValue(CheckBoxVisibilityProperty, value); }
    }

    // Using a DependencyProperty as the backing store for IsCheckBoxVisible.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CheckBoxVisibilityProperty =
        DependencyProperty.Register("CheckBoxVisibility", typeof(Visibility), typeof(UserControlChildView), new PropertyMetadata(Visibility.Collapsed));

Конструктор serControlChildView выглядит так:

    public UserControlChildView()
    {
        InitializeComponent();

        this.LayoutRoot.DataContext = this;
    }

Похоже, это работает! Спасибо за вашу помощь, ребята!

0 голосов
/ 17 мая 2010

Я не вижу весь ваш код, поэтому я не могу решить все, но пара вопросов:

В своем вызове DependencyProperty.Register вы указываете typeof (TopMenuButton), который должен быть UserControlChildView - я не знаю, является ли это ваше представление или нет?

Вы не настроили метод обратного вызова для измененного свойства. Для этого вам нужно определить свойства для FrameworkPropertyMetadata, прежде чем регистрировать зависимостьProperty следующим образом:

FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
metadata.PropertyChangedCallback += OnSpacePropertyChanged;

Затем вам нужно будет объявить OnSpacePropertyChanged, но вы можете по крайней мере ответить на установку свойства оттуда.

...