#c# #.net #wpf
#c# #.net #wpf
Вопрос:
Я работаю над проектом WPF, в котором моя модель представления имеет более 90 свойств. У меня есть кнопка «Сохранить», при нажатии на которую я сохраняю свойства в БД. Я должен отключить кнопку сохранения, пока по крайней мере одно из свойств не будет изменено. Я не могу пойти и включить обработку событий OnPropertyChanged для каждого свойства (просто потому, что это слишком громоздко для более чем 90 свойств). Могу ли я сделать так, чтобы даже при изменении одного свойства я получал уведомление, чтобы я мог включить кнопку сохранения?
<StackPanel>
<StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="{x:Static res:Resources.SaveToDB}" Command="{Binding Save}" IsEnabled="{Binding CanSaveToDB}" Margin="0,0,4,0" HorizontalAlignment="Center" Style="{StaticResource OverlayDialogButtonCentered}" FontSize="14"/>
<Button Content="{x:Static res:Resources.DiscardDBSave}" Command="{Binding DiscardSave}" Margin="0,0,4,0" HorizontalAlignment="Center" Style="{StaticResource OverlayDialogButtonCentered}" FontSize="14"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView1 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View1}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView2 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View2}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView3 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View3}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView4 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View4}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView5 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View5}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView6 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View6}"/>
</StackPanel>
<StackPanel>
<views:MySampleAppView7 DataContextChanged="MySampleApp_DataContextChanged" DataContext="{Binding MySampleApp.View7}"/>
</StackPanel>
</StackPanel>
Тогда каждое из приведенных выше представлений имеет элементы управления WPF.У меня есть viewmodels для каждого из приведенных выше представлений. Затем существует основная модель представления, которая представляет вышеупомянутый код.
Комментарии:
1. Покажите некоторый код, который может помочь нам помочь вам.
2. Добавлен пример кода
3. Просто игнорируйте propertyName в PropertyChangedEventArgs , т. Е. Включите кнопку, как только будет запущено первое событие PropertyChanged, независимо от фактического имени свойства.
Ответ №1:
Типичным решением является реализация его только один раз (обычно в базовом классе) и вызов его из установщика для каждого свойства, передающего имя измененного свойства. Это все еще относительно громоздко. Другой подход заключается в использовании такого инструмента, как Fody, для автоматического добавления этой логики. Если все ваши свойства вызывают единую OnPropertyChanged
реализацию, то логика для установки грязного флага (и, следовательно, включения кнопки сохранения) может быть реализована там.
Комментарии:
1. Спасибо, можно использовать инструмент, и повторная установка параметра для каждого свойства — та же проблема
Ответ №2:
Согласно документации,
Событие PropertyChanged может указывать на то, что все свойства объекта изменились с помощью null или String .Пусто как имя свойства в PropertyChangedEventArgs .
Комментарии:
1. Это не решает проблему OP, связанную с необходимостью реализации уведомления при изменении значения для всех 90 свойств.
Ответ №3:
На ум приходят два способа.
Во-первых, вам действительно не нужно запускать уникальное уведомление об изменении свойства в каждом установщике свойств, потому что свойства IsEnabled ваших кнопок не будут привязаны ни к одному из этих 90 с лишним свойств в вашей модели представления. Я думаю, что вы действительно хотите иметь какое-то свойство IsDirty, которое устанавливается при изменении одного из других свойств, привязать его к свойству IsEnabled кнопок и выполнить уведомитель OnPropertyChanged при изменении IsDirty.
Однако, если вы по-прежнему не хотите делать НИЧЕГО особенного в своих 90 установщиках свойств, другой вариант — обработать событие изменения в самих элементах управления представлением. Например, во всех текстовых полях подписаться на TextChanged . И в ваших обработчиках событий установите свойство IsDirty для вашей модели представления. (Вы можете подписаться на эти обработчики в стилях элементов управления, поэтому вам не нужно устанавливать обработчик событий 90 раз.)
За исключением этих двух идей, я не думаю, что есть какой-либо способ сделать то, что вы хотите. В C # нет встроенного механизма для получения уведомлений об изменении свойства класса. Вам придется перехватить изменение самостоятельно, если не в установщиках свойств, то с помощью обработчиков событий для элементов управления, к которым они привязаны.
Комментарии:
1. Спасибо, я попробую это, но я ищу лучшие варианты
2. Пожалуйста, дайте нам знать, если вы найдете его! Мне самому было бы очень любопытно.
3. Я использовал первый вариант, предложенный open-collar, не мог сделать это никаким другим способом
4. Я не скажу, что мы вам это говорили. 🙂