Arhn - архитектура программирования

Привязка к свойству во вложенных объектах в коде позади

Вложенная ViewModel устанавливается в MainWindow DataContext:

var mainWindow = new MainWindow();
mainWindow.Show();
mainWindow.DataContext = new
{
    MyProperty = new
    {
        MySubProperty = "Hello"
    }
}

Привязать к MySubProperty в XAML легко:

<Button Content="{Binding MyProperty.MySubProperty}"/>

Как я могу сделать эту привязку в коде позади?

// MyButton.xaml.cs
public partial class MyButton : Button
{
    public MyButton()
    {
        InitializeComponent();
        // todo: add binding here
    }

    // I want this method called if this datacontext is set.
    // and called if MySubProperty changes and INotifyPropertyChange is implemented in the Datacontext.
    public void MySubPropertyChanged(string newValue)
    {
        // ...
    }
}

У меня нет доступа к MainWindow в MyButton.xaml.cs, поэтому я не могу использовать его в качестве источника.

Кнопка — это всего лишь пример, но это было бы началом. В моем исходном сценарии у меня нет полезного свойства зависимости для этого. Если для такой привязки необходим dp, был бы очень полезен пример, включающий создание dp.


Ответы:


1

Как насчет этого? (просто грязный и непроверенный пример, в принципе должно работать)

// MyButton.xaml.cs
public partial class MyButton : Button
{
    public MyButton()
    {
        InitializeComponent();
        this.DataContextChanged += DataContext_Changed;
    }

    private void DataContext_Changed(Object sender,DependencyPropertyChangedEventArgs e)
    {
       INotifyPropertyChanged notify = e.NewValue as INotifyPropertyChanged;
       if(null != notify)
       {
          notify.PropertyChanged += DataContext_PropertyChanged;
       }
    }

    private void DataContext_PropertyChanged(Object sender,PropertyChangedEventArgs e)   
    {
        if(e.PropertyName == "MySubProperty")
           MySubPropertyChanged((sender as YourClass).MySubProperty);
    } 

    public void MySubPropertyChanged(string newValue)
    {
        // ...
    }
}

РЕДАКТИРОВАТЬ:

для привязки чего-либо в отделенном коде вы можете использовать:

Binding binding = new Binding();
// directly to myproperty
binding.Source = MyProperty;
binding.Path = new PropertyPath("MySubProperty");
// or window
binding.Source = mainWindow; // instance
binding.Path = new PropertyPath("MyProperty.MySubProperty");

// then wire it up with (button is your MyButton instance)
button.SetBinding(MyButton.MyStorageProperty, binding);
//or
BindingOperations.SetBinding(button, MyButton.MyStorageProperty, binding);
11.09.2010
  • Большое спасибо, что нашли время ответить. Я не знал / я забыл, что DataContextChanged вызывается, если родительский DataContext изменен. Однако усилия по кодированию увеличиваются, если данные более вложены, так что это не кажется лучшим способом. Поэтому я не буду устанавливать ваш ответ как принятый ответ. 11.09.2010
  • @ ваше редактирование: спасибо. Но у меня нет ни экземпляра MyProperty, ни экземпляра MainWindow в классе MyButton. 11.09.2010
  • Если вы привязываетесь, вы установили его в DataContext 11.09.2010
  • Ах хорошо. поэтому мне все еще нужен DataContext_Changed. Я понял :) 11.09.2010

  • 2

    В моей исходной проблеме у меня не было свойства зависимости. Поэтому я создал один.

    public partial class MyButton : Button
    {
        //...
    
        public string MyStorage
        {
            get { return (string)GetValue(MyStorageProperty); }
            set { SetValue(MyStorageProperty, value); }
        }
    
        public static DependecyProperty MyStorageProperty = 
            DependencyProperty.Register("MyStorage", typeof(string), typeof(MyButton),
                new UIPropertyMetadata(OnMyStorageChanged));
        public static void OnMyStorageChanged(DependecyObject d, DependencyPropertyChangedEventArgs e)
        {
            var myButton = d as MyButton;
            if (myButton == null)
                return;
            myButton.OnMyStorageChanged(d,e);
        }
    
        public void OnMyStorageChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            // ...
        }
    }
    

    И теперь я могу установить привязку в XAML

    <local:MyButton MyStorage="{Binding MyProperty.MySubProperty}"/>
    

    Это решило мою проблему. Но мне все еще любопытно, как сделать эту привязку без XAML.

    11.09.2010
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..