Привязка WPF TextBlock к DependencyProperty

Asked
Viewd11416

1

У меня есть то, что я считаю одним из самых простых случаев попытки привязать представление к свойству зависимостей в модели представления. Кажется, что первоначальные изменения отражены в представлении, но другие изменения в DP не обновляют TextBlock представления. Я, наверное, просто упускаю что-то простое, но я просто не вижу, что это такое. Пожалуйста, посмотрите ...

Мой XAML имеет строку состояния в нижней части окна. Хочу привязать к ДП "VRAStatus".

         <StatusBar x:Name="sbar" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" 
               VerticalAlignment="Bottom" Background="LightBlue" Opacity="0.4" DockPanel.Dock="Bottom" >
            <StatusBarItem>
                <TextBlock x:Name="statusBar" Text="{Binding VRAStatus}" />
            </StatusBarItem>
            <StatusBarItem>
                <Separator Style="{StaticResource StatusBarSeparatorStyle}"/>
            </StatusBarItem>
        </StatusBar>
 

В моей модели просмотра определен DP:

     public string VRAStatus
    {
        get { return (string)GetValue(VRAStatusProperty); }
        set { SetValue(VRAStatusProperty, value); }
    }

    // Using a DependencyProperty as the backing store for VRAStatus. 
    public static readonly DependencyProperty VRAStatusProperty =
        DependencyProperty.Register("VRAStatus", typeof(string), typeof(PenskeRouteAssistViewModel),new PropertyMetadata(string.Empty));
 

Затем в моем коде я установил DP:

         VRAStatus = "Test Message...";
 

Есть ли здесь что-то очевидное, чего мне не хватает? В моем конструкторе для модели представления я установил DP следующим образом:

         VRAStatus = "Ready";
 

Мне никогда не удается отобразить тестовое сообщение.

5 ответов

0

Попробуйте указать имя DP с флагом Path в привязке следующим образом:

 <TextBlock x:Name="statusBar" Text="{Binding Path=VRAStatus}">
 
  • Еще один хороший вопрос - да, он происходит от класса ViewModelBase, который:

    общедоступный абстрактный класс ViewModelBase: DependencyObject, INotifyPropertyChanged, IDisposable

    В противном случае методы GetValue и SetValue не были бы определены.

    Bill Campbell03 июня 2009, 19:35
  • [Binding Path =…] использует конструктор по умолчанию и устанавливает для свойства path объекта привязки значение. {Binding…} вызывает конструктор, который принимает один аргумент, который является путем. http://msdn.microsoft.com/en-us/library/system.windows.data.binding.binding.aspx

    Cameron MacFarland06 июня 2009, 13:45
  • Еще раз спасибо! Я считаю, что по умолчанию используется двусторонняя привязка. Я все равно пробовал без изменений. Должно быть, я упустил что-то действительно глупое.

    Bill Campbell03 июня 2009, 18:50
  • Спасибо, стевозавр! Я пробовал как с Path, так и без него и получил тот же результат. Любопытно, что когда я устанавливаю точку останова после установки свойства в «Test Message…» и нахожу указатель мыши на имя «VRAStatus» в XAML, в нем действительно есть «Test Message…» в качестве значения.

    Bill Campbell03 июня 2009, 18:11
  • Да, я не был уверен, что это изменит ситуацию, поскольку я только сам изучаю WPF. Кажется странным, что вы можете получить доступ к новому значению. Вы пробовали указать режим привязки как TwoWay? Что-то вроде {Binding Path = VRAStatus, Mode = TwoWay}

    stevosaurus03 июня 2009, 18:15
  • Хм, ваш PenskeRouteAssistViewModel унаследован от DependencyObject? Кажется, что текстовое поле может не получать уведомление об изменении свойства, поскольку похоже, что привязка настроена правильно.

    stevosaurus03 июня 2009, 19:28
4

Вам необходимо добавить DataContext = "{Binding RelativeSource = {RelativeSource Self}} в.

"
0

Попробуйте указать свойство UpdateSourceTrigger Binding:

 <StatusBar x:Name="sbar" Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2" 
           VerticalAlignment="Bottom" Background="LightBlue" Opacity="0.4" DockPanel.Dock="Bottom" >
        <StatusBarItem>
            <TextBlock x:Name="statusBar" Text="{Binding VRAStatus, UpdateSourceTrigger=PropertyChanged}" />
        </StatusBarItem>
        <StatusBarItem>
            <Separator Style="{StaticResource StatusBarSeparatorStyle}"/>
        </StatusBarItem>
    </StatusBar>
 
0

Билл

Когда и где вы устанавливаете DataContext? У меня были проблемы в прошлом, когда я устанавливал DataContext перед InitializeComponent, мои привязки никогда не выполнялись должным образом.

Кроме того, ради любопытства: почему вы используете DP в вашей модели просмотра, а не просто Property?

  • Я искал это в Google, и, по всей видимости, есть больше людей, которым сложно привязать свою ViewModel к DP: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/477433d0-76cc-40d2-be1d-ffe8e952e1fd

    Возможно, вы захотите вместо этого использовать POCO. Я думаю, что DP - это немного ОТТ для того, чего вы пытаетесь достичь?

    http://stackoverflow.com/questions/291518/inotifypropertychanged-vs-dependencyproperty-in-viewmodel

    user11288904 июня 2009, 00:43
  • Сожалею, что в моем последнем ответе не было элементов управления кареткой - его довольно трудно читать.

    Bill Campbell03 июня 2009, 22:53
  • И вы устанавливаете DataContext на ViewModel, а не на View? То есть:

    this.DataContext = myViewModel;

    Вместо:

    this.DataContext = this;

    user11288903 июня 2009, 21:08
  • Вы также совершенно уверены, что DataContext тоже не установлен где-то еще?

    user11288903 июня 2009, 21:07
  • да, вот мой app.xaml.cs:

       // Create the ViewModel to which the main window binds
      var ViewModel = new ViewModel(dockManager);
    
      //Show the main window
      PRA vRAWindow = new PRA(ViewModel);
     

    и конструктор представления:

         public PRA(ViewModel vm)
        {
            viewModel = vm;
            DataContext = vm;
    
            InitializeComponent();
        }
     

    Мы очень старались не устанавливать DataContext в каких-либо других местах. Пожалуйста, дайте мне знать, если вы думаете о чем-то еще, и спасибо, что нашли время и хороший ответ!

    Bill Campbell03 июня 2009, 22:51
  • Привет, франция! Да, я думаю, что мне, возможно, придется прибегнуть к POCO, по крайней мере временно, но если я не смогу сделать работу DP, как рекламируется, будет еще труднее делать более сложные вещи, к чему я и иду. Одной из основных функций WPF является DP и привязка данных, поэтому я уверен, что мне не хватает какой-то тонкой вещи (например, TextBlock Text не является DP и, следовательно, не поддерживает двухстороннюю привязку, что не является т правда). Но спасибо за ваши мысли по этому поводу!

    Bill Campbell04 июня 2009, 13:04
  • Еще одна хорошая идея. Сначала я создаю свою модель представления, а затем передаю ее конструктору представления, и я устанавливал DataContext перед вызовом InitializeComponent (). Я переместил его после него и без изменений. Я думал, что использование DP вместо POCO было хорошим и простым способом предоставить легко обновляемое поле. Предполагается, что DP будет более эффективно использовать память и так далее. Я, вероятно, могу сделать это простым свойством и просто реализовать материал PropertyChanged. Я просто не понимаю, почему это не работает. Я думал, что это главный аргумент в пользу WPF.

    Bill Campbell03 июня 2009, 21:00
1

Как оказалось, все оказалось немного сложнее, чем я думал (например, когда это НЕ так? :) Мой RibbonControl находился в UserControl, чтобы получить весь этот XAML из MainWindow. Тот факт, что он был в UserControl, заставлял его работать по-другому с ViewModel. Не знаю почему - наверное, одна из тех загадок, которую никогда не разгадать. Но если поместить мой RibbonControl непосредственно в MainWindow, все будет работать должным образом - как с DP, так и со свойством C #. Интересный. (Хотел бы я вернуть те два дня своей жизни!)

спасибо, Билл