- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我对我的最新应用程序有点困惑。
这是一个使用 MVVM Light 和 Fluent.Validation 的 Master-Detail WPF MVVM 应用程序。
View 的 DataContext 是 MainViewModel : ViewModelBase
用ObservableCollection<ProviderDto>
对于左侧的 ListView 和属性 ProviderDto SelectedProvider
右侧的详细属性。
还有几个RelayCommands
添加、编辑和删除单个 ProviderDto
的
ViewModel 使用 ProviderService
执行这些操作,这些操作通过 mvvmlight 的 SimpleIoC
注入(inject)到它的构造函数中在一个单独的ViewModelLocator
.
到目前为止一切正常,我还设法获得了设计时数据。
我现在尝试将 Fluent.Validation 添加到 Mix 并按照 this post 中的描述进行实现(我的 ProviderDto
现在继承自 ValidationBase
而不是 ObservableObject
。Base 现在继承自 ObservableObject
。而且我在 ProviderDtoValidator
中注册了 ViewModelLocator
。)
这让我可以自动验证我的 ObservableObjects 并调用 .IsValid
在他们身上。
到目前为止一切顺利,我相信我能够让它适应 View 并使那些错误框变红 :)。
现在回答我真正的问题:
我想在 View 上有一个按钮来保存对 SelectedProvider
的更改.这自然应该与此绑定(bind):
Relaycommand SaveProviderCommand = new RelayCommand(SaveProvider, CanSaveProvider)
private bool CanSaveProvider()
{
return SelectedProvider.IsValid;
}
private void SaveProvider()
{
if (SelectedProvider.IsValid)
_providerController.SaveProvider(SelectedProvider);
}
我应该把 SaveProviderCommand SaveCommand 放在哪里?
如果我将它放在 ViewModel 中,那么我只能从 SelectedProvider-Property 中调用它:
public ProviderDto SelectedProvider
{
get { return _selectedProvider; }
set
{
Set(() => SelectedProvider, ref prV_selectedProvider, value);
SaveProviderCommand.RaiseCanExecuteChanged(); // Here!
}
}
当 SelectedProvider
中只有一个属性时,这显然不起作用。发生变化。
另一种可能性是将命令放在 DTO 本身上,并在每次更改属性时调用它。例如,当电子邮件属性更改时:
//A Property from Provider
public string Email
{
get { return _email; }
set
{
Set(() => Email, ref _email, value.TrimSafe());
SaveProviderCommand.RaiseCanExecuteChanged(); // Here!
}
}
这里的优点是,当我更改每个属性时,验证工作开箱即用,直到 View 级别。缺点是我必须注入(inject) ProviderController
在 DTO 的构造函数中,因此可以在私有(private)保存方法中调用它。我认为 DTO 不应该知道如何自救。它只应该能够判断它是否.IsValid
保存逻辑应该属于 ViewModel。
我希望你能看到我的困境:
如果我将 SaveCommand 放在 ViewModel 中,那么我将不得不做我不知道如何在 View 中验证我的 SelectedProvider。验证将如何工作?我查看了控件的 DataTemplating,但我似乎无法使其与 Fluent.Validation 一起工作。
如果我将 SaveCommand 放在 DTO 本身中,那么验证会很好地工作,但我认为在应该保持愚蠢的东西中注入(inject)如此多的功能是不正确的。
当然这是一个浓缩的例子,但我认为足以说明问题。希望得到一些关于模式和实践的好的建议。
最佳答案
我找到了解决这个问题的合适方法,也许它会对其他人有所帮助。
由于 Viewmodel 中的 SelectedProvider 及其单个属性都实现了 INotifyPropertyChanged(通过 ViewModelBase 或 ObservableObject),因此我可以简单地订阅 ViewModel 中的 SelectedProvider.PropertyChanged。
public MainViewModel()
{
// Constructor
if (SelectedProvider != null)
SelectedProvider.PropertyChanged += SelectedProvider_PropertyChanged;
}
private void SelectedProvider_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
SaveProviderCommand.RaiseCanExecuteChanged();
}
在 View 中,我可以根据 this post 实现控件
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel>
<Grid DockPanel.Dock="Right" Width="16" Height="16"
VerticalAlignment="Center" Margin="3 0 0 0">
<Ellipse Width="16" Height="16" Fill="Red"/>
<Ellipse Width="3" Height="8"
VerticalAlignment="Top" HorizontalAlignment="Center"
Margin="0 2 0 0" Fill="White"/>
<Ellipse Width="2" Height="2" VerticalAlignment="Bottom"
HorizontalAlignment="Center" Margin="0 0 0 2"
Fill="White"/>
</Grid>
<Border BorderBrush="Red" BorderThickness="2" CornerRadius="2">
<AdornedElementPlaceholder/>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource=
{x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<TextBox Name="TxtEmail" Margin="5" Text="{Binding Path=SelectedProvider.Email,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, Mode=TwoWay}" />
这种方法为我提供了我想要的关注点分离和开箱即用的验证。唯一的小缺点:我觉得在 VM 中进行事件订阅不太美观......
关于c# - 带有 mvvmlight 和 Fluent.Validation 的 WPF MVVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31695804/
我们在 WPF 中使用 MVVMLight。我们的 View 和 View 模型驻留在不同的项目中。 Views 中发生的所有未处理的异常都可以由 app.xaml.cs 文件处理,但我们也希望通过提
我在Silverlight 5中使用MVVMLight。 有谁知道为什么它不能发送空消息? 我正在使用Send(TMessage消息) Messenger.Default.Send(null); 通常
我的项目中有一个奇怪的行为。我使用 MvvmLight messenger 来通知我的 UI 的不同部分进行更新。 public EntryViewModel(MenuViewModel men
MvvmLight的ViewModelBase类型具有由所有子类继承的IsInDesignMode属性。 我的MainWindow ViewModel类似于: class MainWindowView
我正在使用MvvmLight,并已使用MessengerInstance.Send(...)方法在某些ViewModel之间实现了通信。效果很好! 不过,最近,我已经从使用同步方法转移到了异步方法来检
各位,我正在使用 WPF 开发 MVVMLight 应用程序,但我的问题是我想在用户加载页面后触发 Loaded 事件。例如我有一些导航页面,所以每当用户点击任何页面时,都应该触发 PageLoade
根据 MSDN doc on PropertyChanged ,如果将空字符串传递给该方法,则会刷新所有属性。使用MvvmLight RaisePropertyChanged 时有这样的事情吗?传递
我有什么 使用 MVVMLight,我有一些在可移植项目中声明的服务接口(interface)以及在 Windows Phone 项目 (WP8.1 SL) 中的相应实现。为了注册实现,我在 App
我正在编写使用 MVVMLight 的 WPF 应用程序。我有一个 DataGrid,我想将选择行的事件连接到命令。这是最简单的部分。困难的部分(当然对我来说 ;])是获取与选定行相关联的实体。我该怎
你好 我通过连接到 MVVM 的 EventToCommand 获得了这个 xaml,此代码的问题是,在离开包含它的页面后,它始终保留在内存中。
我对现有的 MVVMlight 导航界面方法不太满意,而且这种方法非常少,我想实现我自己的导航界面,我可以在其中公开复杂的方法来操作导航堆栈并将其与 MVVM 灯集成。 非常感谢任何关于实现这一目标的
这个问题可能看起来很幼稚,但我无法理解 ViewModelLocator.cs 文件中的这段代码: static ViewModelLocator() { ServiceLocator.Set
是否可以编写一个调用 Messenger.Default.Register 方法的单元测试,然后编写一个供 Action 使用的 Assertion? 我想确定我的 ViewModel 在对我的一个命
"Could not load file or assembly 'GalaSoft.MvvmLight, Version=5.4.1.0, Culture=neutral, PublicKeyTok
xaml View 模型 public ProductVM() {
我在 Windows Phone 8 项目中使用 GalaSoft - MVVM Light Toolkit 时遇到了一个相当奇怪的问题。突然(在合并一些东西之后)我所有的 EventToComman
我在开发 Windows 应用商店应用程序时遇到了一个大问题。我前段时间描述了我的解决方案架构in this question .我将 MvvmLight 添加到我的包含表示逻辑的可移植类库中,然后我
这个测试不应该通过吗: [TestMethod] public void derived_message_subscription() { bool handled = false;
我正在使用 Xamarin iOS 和 Xamarin Android 设计一个跨平台应用程序架构,我决定使用 MvvmLight,它看起来不错,并且没有隐藏 MVVM 模式的所有内容,非常好而且灵活
我正在构建一个应用程序来自学 MVVM 并通过一些谷歌搜索(和一些尝试错误)我已经设法达到可以从 ViewModel 打开第二个窗口但不能从一个页面传递变量的地步给另一个。这是我的 View 模型。
我是一名优秀的程序员,十分优秀!