数据绑定方向——Model
namespace System.Windows.Data
{
public enum BindingMode
{
TwoWay = 0,
OneWay = 1,
OneTime = 2,
OneWayToSource = 3,
Default = 4
}
}
TwoWay = 0,
绑定的双方,值可以相互传递
OneWay = 1,
绑定后,数据从源到目标 Data.Value->TextBox.Text
OneTime = 2,
绑定的双向,在初始化的时候,数据同步一次,Data.Value->TextBox.Text
OneWayToSource = 3,
绑定后,数据从目标到源,TextBox.Text->Data.Value
Default = 4
默认,没有写Model属性的时候是这个值,目标依赖属性的什么形式就是什么形式
public class Data
{
public string Value { get; set; } = "123";
}
<TabItem Header="关于Mode属性">
<StackPanel>
<!--==================关于Mode属性=========================-->
<!--TextBlock的Text属性默认是单向绑定,TextBox的Text属性默认是双向绑定-->
<TextBlock Text="{Binding Value}"/>
<!--原因是:上面对象是只是做显示,下面对象可以做编辑(页面输入时,信息会回写,写到Value属性里去)-->
<!--这里问题与Value的属性类型无关-->
<TextBox Text="{Binding Value,Mode=TwoWay}"/>
<TextBox Text="{Binding Value,Mode=OneTime}"/>
<TextBox Text="{Binding Value,Mode=OneWayToSource}"/>
<TextBox/>
</StackPanel>
</TabItem>
更新数据源时机——UpdateSourceTrigger
namespace System.Windows.Data
{
public enum UpdateSourceTrigger
{
Default = 0,
PropertyChanged = 1,
LostFocus = 2,
Explicit = 3
}
}
Default = 0,
不更新源
PropertyChanged = 1,
属性值发生变化的时候,更新源
LostFocus = 2,
失去焦点,更新源
Explicit = 3
明确的告诉进行更新
<TabItem Header="关于UpdateSourceTrigger属性">
<StackPanel>
<!--==============关于UpdateSourceTrigger属性==============-->
<!--TextBox的Text属性推送给源的时机是控件失去焦点-->
<Button Content="Button" Click="Button_Click"/>
<TextBox Text="{Binding Value,Mode=TwoWay}"/>
<TextBox Text="{Binding Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding Value,Mode=TwoWay,UpdateSourceTrigger=Explicit}" Name="tb"/>
</StackPanel>
</TabItem>
private void Button_Click(object sender, RoutedEventArgs e)
{
// 获取对应控件属性的绑定表达式
BindingExpression bindingExpression = tb.GetBindingExpression(TextBox.TextProperty);
// 指定更新源
bindingExpression.UpdateSource();
}
延时更新数据源——Delay
<TabItem Header="关于Delay属性">
<!--
// 变化的时候做什么逻辑
// UpdateSrouce的时候,每次变化都会触发Set,如果Set里有逻辑 跟不上,
// 希望每次输入都能直接触发更新,不需要失去焦点,不希望每个字符都更新
// 可以让更新的时机稍等下 Delay
// Text属性被连续更新后多少毫秒
-->
<StackPanel>
<!--这里更新的时机是失去焦点,Delay无效,不会等待2000-->
<TextBox Text="{Binding Value,Mode=TwoWay,Delay=2000}"/>
<!--实时同步更新源的时候,可以等待-->
<TextBox Text="{Binding Value,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,Delay=2000}"/>
<TextBox/>
</StackPanel>
</TabItem>
数据显示格式——StringFormat
<TabItem Header="StringFormat">
<StackPanel>
<TextBlock Text="{Binding IntValue,StringFormat={}{0:000000}}"/>
<TextBlock Text="{Binding IntValue,StringFormat={}{0:P2}}"/>
<TextBlock Text="{Binding FloatValue,StringFormat={}{0:0.000}}"/>
<TextBlock Text="{Binding FloatValue,StringFormat={}{0:N3}}"/>
<TextBlock Text="{Binding FloatValue,StringFormat={}{0:C3},ConverterCulture=zh-cn}"/>
<TextBlock Text="{Binding DateTimeValue,StringFormat={}{0:yyyy-MM-dd}}"/>
<Border Height="1" Background="Red"/>
<TextBlock Text="{Binding IntValue,StringFormat=\{0:000000\}}"/>
<TextBlock Text="{Binding IntValue,StringFormat=\{0:P2\}}"/>
</StackPanel>
</TabItem>
触发器——Converter
使用自定义触发器转义字符
public class Data
{
public string Value { get; set; } = "123";
public int IntValue { get; set; } = 100;
public float FloatValue { get; set; } = 0.1f;
public DateTime DateTimeValue { get; set; } = DateTime.Now;
public int CodeValue { get; set; } = 64; // '@'
public Data()
{
//IntValue.ToString("000000.00");
//DateTimeValue.ToString("yyyy-MM-dd HH:mm:ss");
}
}
// MarupExtension这个基类不是必须继承,主要目标是希望CharConverter可以以{}的形式在XAML中实例化
// 比如:<TextBlock Text="{Binding CodeValue,Converter={local:CharConverter}}"/>
// 没有继承MarkupExtensionn的情况下,XAML中以资源或标签对象的方式进行引用
// 比如:<TextBlock Text="{Binding CodeValue,Converter={StaticResource cc}}"/>
public class CharConverter :MarkupExtension, IValueConverter
{
// 数据从源到目标的时候,执行这个方法,将这个方法的结果显示在目标
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//int.Parse(value.ToString()) * 0.1;
// &#@e618
// (char)e618 ' '
// 源的数据 64 int
return (char)int.Parse(value.ToString());
}
// 数据从目标到源的时候。执行这个方法,将这个方法的结果提交给源
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// 目标的数据 a 97
//value
return (int)(value.ToString()[0]);
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
<Window.Resources>
<local:CharConverter x:Key="cc"/>
</Window.Resources>
<TabItem Header="Converter">
<StackPanel>
<!--这种方式需要CharConverter实现MarkupExtension基类-->
<TextBlock Text="{Binding CodeValue,Converter={local:CharConverter}}"/>
<!--这种方式需要提前定义资源-->
<TextBlock Text="{Binding CodeValue,Converter={StaticResource cc}}"/>
<!--这种方式 可以不用定义资源-->
<TextBlock>
<TextBlock.Text>
<Binding Path="CodeValue">
<Binding.Converter>
<local:CharConverter/>
</Binding.Converter>
</Binding>
</TextBlock.Text>
</TextBlock>
<TextBox Text="{Binding CodeValue,Converter={StaticResource cc},UpdateSourceTrigger=PropertyChanged}"
TextChanged="TextBox_TextChanged">
</TextBox>
</StackPanel>
</TabItem>
使用系统默认触发器转换控件属性
<Window.Resources>
<!--自定义转换器-->
<local:CharConverter x:Key="cc"/>
<!--系统默认的转换器,非常常用-->
<BooleanToVisibilityConverter x:Key="btv"/>
<!--主要针对GroupBox的边框处理,不常用-->
<BorderGapMaskConverter x:Key="bgmc"/>
</Window.Resources>
<CheckBox Content="展开" VerticalContentAlignment="Center" IsChecked="{x:Null}"
Name="cb"/>
<Border Height="30" Background="Orange"
Visibility="{Binding ElementName=cb,Path=IsChecked,Converter={StaticResource btv}}"/>
<Window.Resources>
<AlternationConverter x:Key="ac">
<SolidColorBrush>red</SolidColorBrush>
<SolidColorBrush>Green</SolidColorBrush>
<SolidColorBrush>orange</SolidColorBrush>
</AlternationConverter>
<x:Array Type="sys:Int32" x:Key="adatas">
<sys:Int32>1</sys:Int32>
<sys:Int32>2</sys:Int32>
<sys:Int32>3</sys:Int32>
<sys:Int32>4</sys:Int32>
<sys:Int32>5</sys:Int32>
</x:Array>
<Style TargetType="ListBoxItem">
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},Path=(ItemsControl.AlternationIndex),Converter={StaticResource ac}}"/>
</Style>
</Window.Resources>
<ListBox ItemsSource="{StaticResource adatas}" AlternationCount="3">
触发器参数传递——ConverterParameter
// 1:男 2:女
public int Gender { get; set; } = 2;
// MarupExtension这个基类不是必须继承,主要目标是希望CharConverter可以以{}的形式在XAML中实例化
// 比如:<TextBlock Text="{Binding CodeValue,Converter={local:CharConverter}}"/>
// 没有继承MarkupExtensionn的情况下,XAML中以资源或标签对象的方式进行引用
// 比如:<TextBlock Text="{Binding CodeValue,Converter={StaticResource cc}}"/>
public class CharConverter : MarkupExtension, IValueConverter
{
// 数据从源到目标的时候,执行这个方法,将这个方法的结果显示在目标
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//int.Parse(value.ToString()) * 0.1;
// &#@e618
// (char)e618 ' '
// 源的数据 64 int
int p = parameter == null ? 0 : int.Parse(parameter.ToString());
return (char)(int.Parse(value.ToString()) + p);
}
// 数据从目标到源的时候。执行这个方法,将这个方法的结果提交给源
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// 目标的数据 a 97
//value
return (int)(value.ToString()[0]);
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
public class GenderConverter : IValueConverter
{
// 源 到 目标(IsChecked bool)
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//value是源的属性值
var v = int.Parse(value.ToString());
var p = int.Parse(parameter.ToString());
if (v == p) return true;
return false;
}
// 目标到 源
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
//value是目标的属性值
if (Boolean.Parse(value.ToString()))
return parameter;
return null;
}
}
<Window.Resources>
<!--自定义转换器-->
<local:CharConverter x:Key="cc"/>
<local:GenderConverter x:Key="gc"/>
</Window.Resources>
<!--ConverterParameter可以参定参数参与到转换器逻辑中,但是不允许绑定动态值-->
<TextBlock Text="{Binding CodeValue,Converter={StaticResource cc},ConverterParameter=0}"/>
<TextBlock Text="{Binding CodeValue,Converter={StaticResource cc},ConverterParameter=2}"/>
<TextBlock Text="{Binding CodeValue,Converter={StaticResource cc},ConverterParameter=4}"/>
<!--小案例:用户编辑窗口,里面有个属性叫性别(可以下拉,RadioButton单选,选项是4个以内用单选)-->
<!--如何区分这两个信息-》数据中的一个属性中-->
<RadioButton Content="男" VerticalContentAlignment="Center"
IsChecked="{Binding Gender,Converter={StaticResource gc},ConverterParameter=1}"/>
<RadioButton Content="女" VerticalContentAlignment="Center"
IsChecked="{Binding Gender,Converter={StaticResource gc},ConverterParameter=2}"/>
绑定异常处理——FallbackValue-TargetNullValue
FallbackValue:无法绑定的时候,显示一个默认值
TargetNullValue:数据源属性的值为Null的时候目标属性中需要显示的信息
public class MyBinding : Binding
{
public MyBinding()
{
this.TargetNullValue = "AAAA";
}
}
<TabItem Header="FallbackValue-TargetNullValue">
<StackPanel>
<!--绑定失败的表示意思是:1、打不到数据源 2、Path路径无效 以上情况FallbackValue的指定值可以呈现-->
<TextBlock Text="{Binding ElementName=cb,Path=aaa,FallbackValue=绑定失败}"/>
<TextBlock Text="{Binding ElementName=cb,Path=IsChecked,FallbackValue=绑定失败,TargetNullValue=空值}"/>
<TextBlock Text="{local:MyBinding ElementName=cb,Path=IsChecked}"/>
</StackPanel>
</TabItem>
数据验证——ValidationRules
系统验证-ExceptionValidationRule
public class Data : INotifyPropertyChanged
{
private int _value;
public event PropertyChangedEventHandler? PropertyChanged;
public int Value
{
get { return _value; }
set
{
if (value == 123)
throw new Exception("比如不能输入123");
_value = value;
}
}
}
<Window.DataContext>
<local:Data/>
</Window.DataContext>
<StackPanel Margin="20">
<TextBox Text="{Binding Value,UpdateSourceTrigger=PropertyChanged}" Name="tb1"/>
<TextBox TabIndex="0" Focusable="True" Name="tb2">
<TextBox.Text>
<Binding Path="Value" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="Get exception" Click="Button_Click"/>
<TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=tb2}" Foreground="Red"/>
</StackPanel>
目标到源自定义验证-ValidationRule
public class ValueValidationRule : ValidationRule
{
// 实例的调用时机:是在界面上控件被绑定的属性发生变化的时候
// 从目标到源过程,做这个处理
// 关于从源中赋值更新的异常提示:IDataErrorInfo
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
// 做值的校验规则
//value参数指的是目标值
if (int.TryParse(value.ToString(), out int v))
{
if (v == 123)
return new ValidationResult(false, "比如不能输入123");
}
else
return new ValidationResult(false, "输入信息不对");
return new ValidationResult(true, string.Empty);
}
}
<StackPanel Margin="20">
<TextBox Text="{Binding Value,UpdateSourceTrigger=PropertyChanged}" Name="tb1"/>
<TextBox TabIndex="0" Focusable="True" Name="tb2">
<TextBox.Text>
<Binding Path="Value" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="Get exception" Click="Button_Click"/>
<TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=tb3}" Foreground="Red"/>
<TextBox TabIndex="0" Focusable="True" Name="tb3">
<TextBox.Text>
<Binding Path="Value" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:ValueValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
源到目标自定义验证-IDataErrorInfo
public class Data : INotifyPropertyChanged, IDataErrorInfo
{
public event PropertyChangedEventHandler? PropertyChanged;
private int _value;
public int Value
{
get { return _value; }
set { _value = value;}
}
// 索引
public string this[string propName]
{
get
{
if (propName == "Value")
{
if (this.Value > 1000)
return "大于1000![IDataErrorInfo]";
}
return "";
}
}
}
<TextBox Text="{Binding Value,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" Name="tb4"/>
ValidatesOnDataErrors验证开关,不设置此属性为True则不进行校验。
标签:object,return,int,绑定,Binding,value,ToString,WPF,public From: https://www.cnblogs.com/ZHIZRL/p/17855343.html