C# 以XAML为单位设置最小值的绑定滑块值
我对WPF绑定行为有些困惑。我在代码隐藏(code behind)中有一个绑定到依赖项属性的滑块值(仅用于示例)。滑块的最小值以XAML为单位设置。加载窗口后,滑块的值设置为最小值,但dependency属性仍具有默认值0。但是,正在调用滑块的ValueChanged回调,因此我实际上希望绑定得到更新 所以我有下面的窗口,一个标签显示滑块值,另一个标签显示值绑定到的属性C# 以XAML为单位设置最小值的绑定滑块值,c#,wpf,binding,C#,Wpf,Binding,我对WPF绑定行为有些困惑。我在代码隐藏(code behind)中有一个绑定到依赖项属性的滑块值(仅用于示例)。滑块的最小值以XAML为单位设置。加载窗口后,滑块的值设置为最小值,但dependency属性仍具有默认值0。但是,正在调用滑块的ValueChanged回调,因此我实际上希望绑定得到更新 所以我有下面的窗口,一个标签显示滑块值,另一个标签显示值绑定到的属性 <Window x:Class="SliderBinding.MainWindow" x
<Window x:Class="SliderBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" x:Name="window">
<StackPanel DataContext="{Binding ElementName=window}">
<Slider Minimum="10" Maximum="100" x:Name="slider" Value="{Binding SliderValue, Mode=TwoWay}" ValueChanged="Slider_OnValueChanged"/>
<Label Content="{Binding Value, ElementName=slider}"></Label>
<Label Content="{Binding SliderValue}"></Label>
</StackPanel>
</Window>
后面的代码包含dependency属性和事件回调,事件回调在滑块值更改时只打印跟踪消息
using System;
using System.Diagnostics;
using System.Windows;
namespace SliderBinding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
/* Sorry, wrong code
public double SliderValue
{
get; set;
}*/
public double SliderValue
{
get { return (double)GetValue(SliderValueProperty); }
set { SetValue(SliderValueProperty, value); }
}
public static readonly DependencyProperty SliderValueProperty =
DependencyProperty.Register("SliderValue", typeof(double), typeof(MainWindow), new PropertyMetadata(default(double)));
private void Slider_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Trace.TraceInformation("Slider value changed to {0}", e.NewValue);
}
}
}
使用系统;
使用系统诊断;
使用System.Windows;
命名空间滑块绑定
{
///
///MainWindow.xaml的交互逻辑
///
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
/*对不起,打错了
公共双滑块值
{
获得;设置;
}*/
公共双滑块值
{
获取{return(double)GetValue(SliderValueProperty);}
set{SetValue(SliderValueProperty,value);}
}
公共静态只读DependencyProperty SliderValueProperty=
Register(“SliderValue”、typeof(double)、typeof(MainWindow)、newpropertyMetadata(default(double));
私有无效滑块\u OnValueChanged(对象发送方,RoutedPropertyChangedEventArgs e)
{
Trace.TraceInformation(“滑块值更改为{0}”,e.NewValue);
}
}
}
只要移动滑块,两个值就相等
我的问题是,当滑块值设置为其最小值时,为什么在启动时不更新dependency属性
以斜体编辑。这里发生的事情是,强制滑动控件的
值
属性,使其位于最小值
和最大值
属性定义的范围内
加载XAML并连接绑定后,将读取零的SliderValue
,WPF将尝试设置值
属性。但是,由于零不在其他属性定义的范围内,因此提供的值会强制进入该范围,因此值
属性保持为10(设置最小值
属性时给出的值)。因此,从标签绑定中可以看出,SliderValue
的值保持为0,而滑块的值保持为10
拖动滑块拇指时,滑块的值
属性将更改。这会导致双向绑定更新,但方向相反(从控件到依赖项属性)。由于DP上没有强制,因此其值将设置为滑块的值。从这一点上说,两者是同步的
您可以通过在窗口中添加一个按钮来验证此行为,然后在OnClick
处理程序中将SliderValue
设置为滑块范围之外的值。您将看到SliderValue
发生更改,但由于强制,滑块的值被设置为其最小值或最大值
值强制是可以为依赖项属性配置的功能之一。阅读更多信息。这里发生的是,滑块控件的值
属性被强制,使其位于最小值
和最大值
属性定义的范围内
加载XAML并连接绑定后,将读取零的SliderValue
,WPF将尝试设置值
属性。但是,由于零不在其他属性定义的范围内,因此提供的值会强制进入该范围,因此值
属性保持为10(设置最小值
属性时给出的值)。因此,从标签绑定中可以看出,SliderValue
的值保持为0,而滑块的值保持为10
拖动滑块拇指时,滑块的值
属性将更改。这会导致双向绑定更新,但方向相反(从控件到依赖项属性)。由于DP上没有强制,因此其值将设置为滑块的值。从这一点上说,两者是同步的
您可以通过在窗口中添加一个按钮来验证此行为,然后在OnClick
处理程序中将SliderValue
设置为滑块范围之外的值。您将看到SliderValue
发生更改,但由于强制,滑块的值被设置为其最小值或最大值
值强制是可以为依赖项属性配置的功能之一。阅读更多信息。这里发生的是,滑块控件的值
属性被强制,使其位于最小值
和最大值
属性定义的范围内
加载XAML并连接绑定后,将读取零的SliderValue
,WPF将尝试设置值
属性。但是,由于零不在其他属性定义的范围内,因此提供的值会强制进入该范围,因此值
属性保持为10(设置最小值
属性时给出的值)。因此<
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(double),
typeof(RangeBase),
new FrameworkPropertyMetadata(
0.0d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault |
FrameworkPropertyMetadataOptions.Journal,
new PropertyChangedCallback(OnValueChanged),
new CoerceValueCallback(ConstrainToRange)),
new ValidateValueCallback(IsValidDoubleValue));
internal static object ConstrainToRange(DependencyObject d, object value)
{
RangeBase ctrl = (RangeBase) d;
double min = ctrl.Minimum;
double v = (double) value;
if (v < min)
{
return min;
}
double max = ctrl.Maximum;
if (v > max)
{
return max;
}
return value;
}
public static readonly DependencyProperty SliderValueProperty =
DependencyProperty.Register("SliderValue", typeof(double), typeof(MainWindow),
new PropertyMetadata(default(double), null, CoerceSliderValue));
private static object CoerceSliderValue(DependencyObject d, object value)
{
// Of course good idea would be to be have min/max as CLR properies
// in your class and bind slider with those values.
// So, that you can have refer to those values directly here.
double min = ((MainWindow)d).slider.Minimum;
double max = ((MainWindow)d).slider.Maximum;
double passedValue = (double)value;
if (passedValue < min)
{
return min;
}
else if (passedValue > max)
{
return max;
}
return passedValue;
}
private void Slider_OnValueChanged(object sender,
RoutedPropertyChangedEventArgs<double> e)
{
CoerceValue(SliderValueProperty);
}