Свойства зависимости WPF ReadOnly с использованием MVVM - PullRequest
7 голосов
/ 17 ноября 2009

Недавно я переопределил сетку DevXpress WPF, чтобы получить свойство SelectedObject, к которому я могу получить доступ из свободно связанной модели ViewModel.

Я создал свойство зависимостей SelectedObject и привязал его к OneWayToSource в своем XAML.

Все работает нормально, но если я пытаюсь сделать его ReadOnly (для полноты), я получаю ошибку компиляции и говорит, что не могу привязать свойство ReadOnly. Приведенный ниже код компилируется, я включил (но rem'd) биты, которые я пытался получить, пытаясь получить свойство ReadOnly.

Может кто-нибудь помочь, пожалуйста?

Свойство зависимости моего переопределенного элемента управления выглядит следующим образом:

  //public static readonly DependencyPropertyKey SelectedRowKey = DependencyProperty.RegisterReadOnly("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null));
//public static readonly DependencyProperty SelectedObjectProperty = SelectedRowKey.DependencyProperty;

public readonly static DependencyProperty SelectedObjectProperty = DependencyProperty.Register("SelectedObject", typeof(object), typeof(MyGrid), new PropertyMetadata(null));

public object SelectedObject
{
    get
    {

        return GetValue(SelectedObjectProperty);
    }
    set
    {
        throw new NotImplementedException();
    }
}

XAML:

 <StackPanel>
  <devxgrid:MyGrid AutoPopulateColumns="True" DataSource="{Binding Animals}" SelectedObject="{Binding MyObject, Mode=OneWayToSource}" Width="300" Height="300">
    <devxgrid:MyGrid.View>
        <MyGrid:TableView AllowEditing="False" Name="GridView" AutoWidth="True" />
    </devxgrid:MyGrid.View>
 </devxgrid:MyGrid>
</StackPanel>

Ответы [ 4 ]

4 голосов
/ 29 августа 2011

Я немного опоздал на этот вопрос, учитывая, что он был задан почти 2 года назад:)

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

<devxgrid:MyGrid AutoPopulateColumns="True"
                 DataSource="{Binding Animals}"
                 Width="300"
                 Height="300">
    <pb:PushBindingManager.PushBindings>
        <pb:PushBinding TargetProperty="SelectedObject" Path="MyObject"/> 
    </pb:PushBindingManager.PushBindings> 
    <!--...-->
</devxgrid:MyGrid> 

PushBinding работает с использованием двух свойств зависимости, Listener и Mirror. Слушатель привязан OneWay к TargetProperty, а в PropertyChangedCallback он обновляет свойство Mirror, привязанное OneWayToSource, к тому, что было указано в привязке.

Демонстрационный проект можно скачать здесь .
Он содержит исходный код и краткий пример использования или посетите мой блог WPF , если вас интересуют подробности реализации.

4 голосов
/ 17 ноября 2009

Вы пытаетесь установить свойство SelectedObject в XAML. Если это только для чтения, как вы можете установить его?

Редактировать: простите, мой плохой. Просто понял, что ты пытаешься сделать, и ты прав, что это должно сработать. Однако WPF не поддерживает этот сценарий, по крайней мере, в версии 3.5.

Редактировать 2: Только что зарегистрирован в .NET 4 и та же история.

Кстати, если вы застряли с чужим DP только для чтения, который вы пытаетесь «протолкнуть» в виртуальную машину, вы можете использовать прикрепленное поведение, чтобы обойти это. Например, предположим, что вы хотите, чтобы ваша виртуальная машина знала свойства ActualWidth и ActualHeight вашего представления. Вы можете написать SizeWatcherBehavior, который присоединяется к FrameworkElement и прослушивает изменения размера. При обнаружении эти изменения размера передаются для чтения / записи вложенных свойств, к которым ваша виртуальная машина может привязаться:

<Grid local:SizeWatcherBehavior.Watch="True"
    local:SizeWatcherBehavior.Width="{Binding WidthOnVM, Mode=OneWayToSource}"
    local:SizeWatcherBehavior.Height="{Binding HeightOnVM, Mode=OneWayToSource}"/>
0 голосов
/ 17 апреля 2018

Пуристы среди нас иначе ожидали бы, что истинный сценарий DependencyProperty только для чтения в идеале должен работать так, как ожидалось. Но для очевидных ожиданий одностороннего и двустороннего связывания данных WPF я согласен в этом направлении.

Тем не менее, я обошел эту проблему в моей DependencyObject модели представления, предоставив полное DependencyProperty, но предоставив только свойство get-only, отображающее детали, которые я хотел. Не совсем для чтения в смысле WPF MVVM, но, поскольку я решил не реализовывать установщик, он работает для моих целей.

Я согласен с другими людьми, любой код, который нарушает MVVM в самом строгом смысле.

0 голосов
/ 10 марта 2010

Мы разрабатываем настраиваемую библиотеку элементов управления, и один из наших пользователей подал запрос на функцию преобразования одного из наших DP из Read-Only в Read-Write, потому что он столкнулся с той же проблемой, что и вы - не может связать OneWayToSource в сценарий MVVM.

Конечно, мы не делали этот DP для чтения-записи.

Использование прикрепленных свойств / поведения для таких сценариев требует больших затрат. Самый простой обходной путь - обработать событие «SelectedObjectChanged» в коде и установить свойство, которое вы хотите привязать к DP «SelectedObject» в коде.

По нашему мнению, этот подход «обрабатывать код события и вызова из VM / DataContext напрямую» никоим образом не нарушает MVVM, поскольку ViewModel по-прежнему ничего не знает о представлении.

...