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

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

Мой XAML имеет строку состояния в нижней части окна. Я хочу привязать к DP "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";

Я никогда не получаю тестовое сообщение для отображения.


person Bill Campbell    schedule 03.06.2009    source источник
comment
Нельзя ли просто привязаться к VRAStatus? И просто сделать VRAStatus строковым свойством в вашей виртуальной машине? например общедоступная строка VRAStatus {получить; set} Любопытно, почему вы думаете, что вам нужно свойство зависимости, Text IS свойство зависимости.   -  person mike gold    schedule 20.08.2020


Ответы (5)


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

person Min Xu    schedule 04.11.2010

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

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

person Bill Campbell    schedule 06.06.2009

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

<TextBlock x:Name="statusBar" Text="{Binding Path=VRAStatus}">
person stevosaurus    schedule 03.06.2009
comment
Спасибо, стевозавр! Я пробовал и с Путем, и без него, и получил тот же результат. Любопытно, что когда я устанавливаю точку останова после установки свойства на Test Message... и наводил указатель мыши на имя VRAStatus в XAML, в нем действительно есть Test Message... как его значение. - person Bill Campbell; 03.06.2009
comment
Да, я не был уверен, что это будет иметь значение, поскольку я сам только изучаю WPF. Кажется странным, что вы можете получить доступ к новому значению. Вы пытались указать режим привязки как TwoWay? Что-то вроде {Binding Path=VRAStatus, Mode=TwoWay} - person stevosaurus; 03.06.2009
comment
Еще раз спасибо! Я считаю, что двусторонняя привязка используется по умолчанию. Я как-то пробовал, без изменений. Я должен пропустить что-то действительно глупое. - person Bill Campbell; 03.06.2009
comment
Хм, ваша модель PenskeRouteAssistViewModel наследуется от DependencyObject? Кажется, что текстовое поле может не получать уведомления об изменении свойства, поскольку похоже, что привязка настроена правильно. - person stevosaurus; 03.06.2009
comment
Еще один хороший вопрос - да, он является производным от класса ViewModelBase, который является: общедоступным абстрактным классом ViewModelBase: DependencyObject, INotifyPropertyChanged, IDisposable. Если бы это было не так, то методы GetValue и SetValue не были бы определены. - person Bill Campbell; 03.06.2009
comment
[Binding Path=...] использует конструктор по умолчанию и задает значение свойства пути объекта привязки. {Binding...} вызывает конструктор, который принимает один аргумент, и этот аргумент является путем. msdn.microsoft.com/en-us/ библиотека/ - person Cameron MacFarland; 06.06.2009

Билл,

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

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

person user112889    schedule 03.06.2009
comment
Еще одна хорошая идея для размышления. Сначала я создаю свою модель представления, а затем передаю ее конструктору представления, и я устанавливал DataContext перед вызовом InitializeComponent(). Я переставил его после него и никаких изменений. Я думал, что использование DP вместо POCO было хорошим и простым способом предоставить легко обновляемое поле. Предполагается, что DP более эффективно использует память и так далее. Вероятно, я могу сделать это простым свойством и просто реализовать материал PropertyChanged. Я просто в замешательстве, почему это не работает. Я думал, что это главный аргумент в пользу WPF. - person Bill Campbell; 04.06.2009
comment
Вы также совершенно уверены, что DataContext не установлен где-то еще? - person user112889; 04.06.2009
comment
И вы устанавливаете DataContext для ViewModel вместо View? То есть: this.DataContext = myViewModel; Вместо: this.DataContext = this; - person user112889; 04.06.2009
comment
yes — вот мой app.xaml.cs: // Создаем ViewModel, к которому привязывается главное окно var ViewModel = new ViewModel(dockManager); //Показать главное окно PRA vRAWindow = new PRA(ViewModel); и конструктор представления: public PRA(ViewModel vm) { viewModel = vm; Контекст данных = ВМ; ИнициализироватьКомпонент(); } Мы очень старались не устанавливать DataContext в каких-либо других местах. Пожалуйста, дайте мне знать, если вы думаете о чем-то еще, и спасибо, что нашли время с хорошим ответом! - person Bill Campbell; 04.06.2009
comment
Извините за то, что в моем последнем ответе не было элементов управления кареткой - это довольно трудно читать. - person Bill Campbell; 04.06.2009
comment
Я искал это в Google, и, по-видимому, есть больше людей, которым трудно привязать свою ViewModel к DP: social.msdn.microsoft.com/Forums/en-US/wpf/thread/ Вместо этого вы можете рассмотреть возможность использования POCO . Я думаю, что DP - это немного OTT для того, чего вы пытаетесь достичь? stackoverflow.com/questions/291518/ - person user112889; 04.06.2009
comment
Привет, Фрэнсис! Да, я думаю, что мне, возможно, придется прибегнуть к POCO хотя бы временно, но если я не смогу заставить DP работать так, как рекламируется, будет еще труднее делать более сложные вещи, к чему я и направляюсь. Одной из основных особенностей WPF является DP и привязка данных, поэтому я уверен, что мне не хватает какой-то тонкой вещи (например, текст TextBlock не является DP и, следовательно, не поддерживает двухстороннюю привязку, что не т верно). Но спасибо за ваши мысли по этому поводу! - person Bill Campbell; 04.06.2009

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

<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>
person sakito    schedule 06.04.2010