如何验证列表框(MVVM)?
Posted
技术标签:
【中文标题】如何验证列表框(MVVM)?【英文标题】:How to validate a ListBox (MVVM)? 【发布时间】:2018-06-27 19:51:13 【问题描述】:我希望我能正确解释我的代码和我的问题,因为它有很多代码。我们正在 Visual Studio 中制作图书管理器应用程序。模型 (Book.cs) 包含书籍的属性(作者、标题、发布等)。
在 MainWindow.xaml 中,我们有一个列表框,其中列出了所有书籍,左侧有对应于属性的标签和文本框(标签“作者”,文本框中显示作者的姓名)。使用此文本框,您可以更新属性。到目前为止,xaml 看起来也是如此:
<Window x:Class="BookApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="clr-namespace:BookApplication.Model"
xmlns:viewModel="clr-namespace:BookApplication.ViewModel"
mc:Ignorable="d"
Title="Book-Manager" Height="350" Width="525">
<Window.Resources>
<model:Book x:Key="myBook" Title="Harry Potter und die Heiligtümer des Todes" Author="J.K.Rowling" Publisher="Carlsen" Edition="1" Release="01.01.2017" ></model:Book>
<viewModel:BookCollectionViewModel x:Key="bcvm"></viewModel:BookCollectionViewModel>
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Datei">
<MenuItem Header="Neu" Command="Binding NewClick, Mode=OneWay, Source=StaticResource bcvm" InputGestureText="Strg+N"/>
<Separator/>
<MenuItem x:Name="Open" Header="Öffnen" Command="Binding LoadClick, Mode=OneWay, Source=StaticResource bcvm" InputGestureText="Strg+O"/>
<MenuItem x:Name="Save" Header="Speichern" Command="Binding SaveClick, Mode=OneWay, Source=StaticResource bcvm" InputGestureText="Strg+S"/>
<MenuItem Header="Speichern unter..." Command="Binding SaveAsClick, Mode=OneWay, Source=StaticResource bcvm"/>
</MenuItem>
<MenuItem Header="Neues Buch" Command="Binding NewBookClick, Mode=OneWay, Source=StaticResource bcvm"></MenuItem>
</Menu>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="252*"/>
<ColumnDefinition Width="265*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Margin="-2,0,0,0">
<Label x:Name="labelTitle" Content="Titel" HorizontalAlignment="Left" Margin="9,10,0,0" VerticalAlignment="Top" Width="46" Height="20" FontSize="8"/>
<TextBox x:Name="textboxTitle" HorizontalAlignment="Left" Height="20" Margin="87,10,0,0" TextWrapping="Wrap" Text="Binding ElementName= BooksListBox, Path=SelectedItem.Title" VerticalAlignment="Top" Width="160" FontSize="8" />
<Label x:Name="labelAuthor" Content="Autor" HorizontalAlignment="Left" Margin="10,30,0,0" VerticalAlignment="Top" Width="62" Height="22" FontSize="8"/>
<TextBox x:Name="textboxAuthor" HorizontalAlignment="Left" Height="18" Margin="87,34,0,0" TextWrapping="Wrap" Text="Binding ElementName=BooksListBox, Path=SelectedItem.Author" VerticalAlignment="Top" Width="160" FontSize="8" />
<Label x:Name="labelPublisher" Content="Verlag" HorizontalAlignment="Left" Margin="10,52,0,0" VerticalAlignment="Top" Width="45" FontSize="8" Height="24"/>
<TextBox x:Name="textboxPublisher" HorizontalAlignment="Left" Height="17" Margin="87,58,0,0" TextWrapping="Wrap" Text="Binding Source=StaticResource myBook, Path=Publisher, Mode=TwoWay" VerticalAlignment="Top" Width="160" FontSize="8" />
<Label x:Name="labelEdition" Content="Auflage" HorizontalAlignment="Left" Margin="10,76,0,0" VerticalAlignment="Top" Width="45" FontSize="8" Height="26"/>
<TextBox x:Name="textboxEdition" HorizontalAlignment="Left" Height="15" Margin="87,79,0,0" TextWrapping="Wrap" Text="Binding ElementName=BooksListBox, Path=SelectedItem.Edition" VerticalAlignment="Top" Width="160" FontSize="8" />
<Label x:Name="labelRelease" Content="Veröffentlichung" HorizontalAlignment="Left" Margin="9,99,0,0" VerticalAlignment="Top" Width="102" FontSize="8"/>
<TextBox x:Name="textboxRelease" HorizontalAlignment="Left" Height="14" Margin="87,103,0,0" TextWrapping="Wrap" Text="Binding ElementName=BooksListBox, Path=SelectedItem.Release, Mode=TwoWay" VerticalAlignment="Top" Width="160" FontSize="8" />
<Label x:Name="labelISBN" Content="ISBN" HorizontalAlignment="Left" Margin="9,120,0,0" VerticalAlignment="Top" Width="81" FontSize="8"/>
<TextBox x:Name="textboxISBN" HorizontalAlignment="Left" Height="14" Margin="87,125,0,0" TextWrapping="Wrap" Text="Binding ElementName=BooksListBox, Path=SelectedItem.Isbn" VerticalAlignment="Top" Width="160" FontSize="8" />
<Button x:Name="buttonRemove" Command="Binding RemoveBookClick, Mode=OneWay, Source=StaticResource bcvm" Content="Löschen" HorizontalAlignment="Left" Margin="9,160,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
<ListBox Grid.Column="1" x:Name="BooksListBox" ItemsSource="Binding Source=StaticResource bcvm" SelectedItem="Binding Source=StaticResource bcvm, Path=SelectedBook">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontWeight="Bold" FontSize="12" Text="Binding Path=Title"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Binding Path=Author"></TextBlock>
<TextBlock Text="; Auflage: "></TextBlock>
<TextBlock Text="Binding Path=Edition"></TextBlock>
</StackPanel>
<Canvas Width="50" Height="12" HorizontalAlignment="Left" >
<Ellipse Name="LeftEllipse" Height="10" Stroke="Black" Fill="Binding Path=ColorLeft" Width="10" Canvas.Left="10"/>
<Ellipse Name="MiddleEllipse" Height="10" Stroke="Black" Fill="Binding Path=ColorMiddle" Width="10" Canvas.Left="30"/>
<Ellipse Name="RightEllipse" Height="10" Stroke="Black" Fill="Binding Path=ColorRight" Width="10" Canvas.Left="50"/>
</Canvas>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DockPanel>
</Window>
如果您单击列表中的任何一本书,属性的值将在左侧的文本框中,您可以编辑这些值,正如我所说的。
现在我必须进行验证。问题是,我只能找到属性的直接验证,而我想验证 ListBox 的值和更新值。
我试过做这样的事情(来源:https://msdn.microsoft.com/es-es/library/ms753962,来源不是英文,但代码很清楚)。
我创建了一个如下所示的 AuthorRule 类:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
namespace BookApplication.Model.Validation
class AuthorRule : ValidationRule
public AuthorRule()
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
if (String.IsNullOrWhiteSpace((String)value))
return new ValidationResult(false, "Dieser Feld ist verpflichtend.");
else
return new ValidationResult(true, null);
只是为了证明,如果字段为空。我的 Model 或 Book.cs 没有改变。 我的 MainWindow.xaml 看起来像这样(它就像另一段代码,但我只会显示 WindowResources 和 TextBox“作者”中的更改):
<Window.Resources>
<model:Book x:Key="myBook" Title="Harry Potter und die Heiligtümer des Todes" Author="J.K.Rowling" Publisher="Carlsen" Edition="1" Release="01.01.2017" ></model:Book>
<viewModel:BookCollectionViewModel x:Key="bcvm"></viewModel:BookCollectionViewModel>
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">
<Run Text="!" />
</TextBlock>
</DockPanel>
</ControlTemplate>
<Style x:Key="textBoxInError" TargetType="x:Type TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="Binding (Validation.Errors)[0].ErrorContent, RelativeSource=x:Static RelativeSource.Self" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
上图是TextBox“作者”的截图,不知道路径和来源应该是什么,所以ListBox还是连着的!!
很抱歉这个问题太长了,有人可以帮我吗?
【问题讨论】:
【参考方案1】:您已经在第一行设置了 Text 属性,并且再次将其设置回节点 TextBox.Text 中。您可能必须首先删除 Text 属性及其值。 此外,源字段不是必需的。 TextBox 的最终解决方案应该是这样的。
<TextBox x:Name="textboxAuthor" HorizontalAlignment="Left" Height="18" Margin="87,34,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="160" FontSize="8" Validation.ErrorTemplate="StaticResource validationTemplate" Style="StaticResource textBoxInError">
<TextBox.Text>
<Binding Path="SelectedItem.Author" ElementName="BooksListBox" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<validation:AuthorRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
这应该可行。
【讨论】:
以上是关于如何验证列表框(MVVM)?的主要内容,如果未能解决你的问题,请参考以下文章