Wii*_*axx 5 c# wpf user-interface mvvm
假设你有一个包含多个这样的Texbox的View
<TextBox Text="{Binding myText1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />
Run Code Online (Sandbox Code Playgroud)
每个都已包含一些文字.如果用户更改此文本,则文本框边框应更改为橙色,如果他撤消其更改,则应获取其默认颜色.
目前我这样做
<TextBox Height="23" Text="{Binding myText1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" BorderThickness="2">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding myDirtyText1, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="BorderBrush" Value="Orange"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Run Code Online (Sandbox Code Playgroud)
有没有更通用/更简单的方法来做到这一点?
编辑
我已经在使用IDataErrorInfo+ System.ComponentModel.DataAnnotations进行错误验证.也许在这种情况下有类似的方法,但我没有发现任何有用的减少我的xaml和代码到最低限度.
我认为你并不真正了解我的问题,所以我会提供一个更好的实际样本:
<Grid Margin="12">
<Label Content="Name:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Width="79" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="102,2,0,0" VerticalAlignment="Top" Width="170" BorderThickness="2"
Text="{Binding NameD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding dirtyName, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="BorderBrush" Value="Orange"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Label Content="Anzeigetext:" Height="28" HorizontalAlignment="Left" Margin="0,34,0,0" VerticalAlignment="Top" Width="79" />
<TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,36,0,0" VerticalAlignment="Top" Width="170"
Text="{Binding AnzeigetextD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding dirtyAnzeigetext, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="BorderBrush" Value="Orange"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Label Content="Preis:" Height="28" HorizontalAlignment="Left" Margin="0,68,0,0" VerticalAlignment="Top" Width="79" />
<TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,70,0,0" VerticalAlignment="Top" Width="170"
Text="{Binding PreisD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, StringFormat=\{0:c\}}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding dirtyPreis, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="BorderBrush" Value="Orange"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Button Content="Speichern" Height="23" HorizontalAlignment="Left" Margin="102,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"/>
<Button Content="Abbrechen" Height="23" HorizontalAlignment="Left" Margin="197,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding CancelCommand}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
public class MenuangebotVM : DetailVM, IContains
{
#region private Values
private Menuangebot myOriginal = new Menuangebot();
private Menuangebot myValue = new Menuangebot();
#endregion // private Values
#region Properties
#region Detail Properties
public int Id { get { return myOriginal.Id; } }
public bool? Result { get; private set; }
public string Beschreibung { get { return "Einrichtung"; } }
[Required]
[RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,40}$")]
public string NameD
{
get { return myValue.Name; }
set
{
myValue.Name = value;
RaisePropertyChanged(() => Reg(() => NameD));
RaisePropertyChanged(() => Reg(() => dirtyName));
}
}
public bool dirtyName
{
get { return (!isNew && myValue.Name != myOriginal.Name) ? true : false; }
}
[Required]
[RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,25}$")]
public string AnzeigetextD
{
get { return myValue.Anzeigetext; }
set
{
myValue.Anzeigetext = value;
RaisePropertyChanged(() => Reg(() => AnzeigetextD));
RaisePropertyChanged(() => Reg(() => dirtyAnzeigetext));
}
}
public bool dirtyAnzeigetext
{
get { return (!isNew && myValue.Anzeigetext != myOriginal.Anzeigetext) ? true : false; }
}
[Required]
public decimal PreisD
{
get { return myValue.Preis; }
set
{
myValue.Preis = value;
RaisePropertyChanged(() => Reg(() => PreisD));
RaisePropertyChanged(() => Reg(() => dirtyPreis));
}
}
public bool dirtyPreis
{
get
{
var value = myValue.Preis;
var Original = myOriginal.Preis;
return (!isNew && value != Original) ? true : false;
}
}
#endregion //Detail Properties
#endregion //Properties
// more code
}
Run Code Online (Sandbox Code Playgroud)
<Grid Margin="12">
<Label Content="Name:" Height="28" HorizontalAlignment="Left" VerticalAlignment="Top" Width="79" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="102,2,0,0" VerticalAlignment="Top" Width="170" BorderThickness="2"
Text="{Binding NameD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, EditesOnDataChanges=true}">
</TextBox>
<Label Content="Anzeigetext:" Height="28" HorizontalAlignment="Left" Margin="0,34,0,0" VerticalAlignment="Top" Width="79" />
<TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,36,0,0" VerticalAlignment="Top" Width="170"
Text="{Binding AnzeigetextD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, EditesOnDataChanges=true}">
</TextBox>
<Label Content="Preis:" Height="28" HorizontalAlignment="Left" Margin="0,68,0,0" VerticalAlignment="Top" Width="79" />
<TextBox BorderThickness="2" Height="23" HorizontalAlignment="Left" Margin="102,70,0,0" VerticalAlignment="Top" Width="170"
Text="{Binding PreisD, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, StringFormat=\{0:c\, EditesOnDataChanges=true}}">
</TextBox>
<Button Content="Speichern" Height="23" HorizontalAlignment="Left" Margin="102,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveCommand}"/>
<Button Content="Abbrechen" Height="23" HorizontalAlignment="Left" Margin="197,110,0,0" VerticalAlignment="Top" Width="75" Command="{Binding CancelCommand}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
public class MenuangebotVM : DetailVM, IContains
{
#region private Values
private Menuangebot myOriginal = new Menuangebot();
private Menuangebot myValue = new Menuangebot();
#endregion // private Values
#region Properties
#region Detail Properties
public int Id { get { return myOriginal.Id; } }
public bool? Result { get; private set; }
public string Beschreibung { get { return "Einrichtung"; } }
[Required]
[RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,40}$")]
[Default(myOriginal.Name)] //<-- added
public string NameD
{
get { return myValue.Name; }
set
{
myValue.Name = value;
RaisePropertyChanged(() => Reg(() => NameD));
}
}
[Required]
[RegularExpression(@"^[0-9a-zA-ZäöüßÄÖÜß''-'\s]{2,25}$")]
[Default(myOriginal.Anzeigetext)] //<-- added
public string AnzeigetextD
{
get { return myValue.Anzeigetext; }
set
{
myValue.Anzeigetext = value;
RaisePropertyChanged(() => Reg(() => AnzeigetextD));
}
}
[Required]
[Default(myOriginal.Preis)] //<-- added
public decimal PreisD
{
get { return myValue.Preis; }
set
{
myValue.Preis = value;
RaisePropertyChanged(() => Reg(() => PreisD));
}
}
#endregion //Detail Properties
#endregion //Properties
// more code
}
Run Code Online (Sandbox Code Playgroud)
public class ViewModel:INotifyPropertyChanged
{
private string initialText;
public ViewModel()
{
Text = "ABCD";
initialText = Text;
DefaultBorder = true;
}
private string text;
public string Text
{
get { return text; }
set { text = value;
if (value == initialText)
DefaultBorder = true;
else
DefaultBorder = false;
Notify("Text"); }
}
private bool defaultBorder;
public bool DefaultBorder
{
get { return defaultBorder; }
set { defaultBorder = value; Notify("DefaultBorder"); }
}
private void Notify(string propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null && value is bool && !(bool)value)
return new SolidColorBrush(Colors.Orange);
else
return new SolidColorBrush(Colors.Navy); //Or default whatever you want
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Window.Resources>
<local:MyConverter x:Key="MyConverter"/>
</Window.Resources>
<Grid>
<TextBox BorderThickness="4" BorderBrush="{Binding DefaultBorder, Converter={StaticResource MyConverter}}" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
Run Code Online (Sandbox Code Playgroud)
在这里,我在 ViewModel 中有属性 Text 绑定到 TextBox,并且在开始时我保留了初始 Text 值。然后每当用户输入时,我在 Text 属性的设置器中对其进行比较并相应地设置 Bool 属性,此 bool 属性将指定使用转换器绑定哪种颜色。忽略小问题希望您能有所了解。