我创建了一个像数字更新的用户控件,如下所示
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" >
<TextBox x:Name="InputTextBox" Grid.Row="0" Grid.Column="0" Grid.RowSpan="1"
Style="{StaticResource NumericUpDownTextBoxStyle}"
KeyDown="InputTextBox_KeyDown"
KeyUp="InputTextBox_KeyUp"
GotFocus="InputTextBox_GotFocus"
LostFocus="InputTextBox_LostFocus"
MouseWheel="InputTextBox_MouseWheel"
MouseEnter="InputTextBox_MouseEnter"
LayoutUpdated="InputTextBox_LayoutUpdated"
Text="{Binding Path=ControlValue, Mode=TwoWay,ValidatesOnDataErrors=True,ValidatesOnExceptions=True,NotifyOnValidationError=True}"/>
</StackPanel>
我已将ViewModel绑定到此控件,其中我将ControlValue属性设置为用户控件模板文本框的TextBox属性。
在控制级别,Everthing工作正常。我已从usercontrol中暴露出来。
public static readonly DependencyProperty MaximumValueProperty;
public static readonly DependencyProperty MinimumValueProperty;
public static readonly DependencyProperty StepValueProperty;
public static readonly DependencyProperty TextValueProperty;
我的属性
public double Maximum
{
get
{
return (double)GetValue(MaximumValueProperty);
}
set
{
SetValue(MaximumValueProperty, value);
this.ViewModel.Maximum = this.Maximum;
}
}
public double Minimum
{
get
{
return (double)GetValue(MinimumValueProperty);
}
set
{
SetValue(MinimumValueProperty, value);
this.ViewModel.Minimum = this.Minimum;
}
}
public double Step
{
get
{
return (double)GetValue(StepValueProperty);
}
set
{
SetValue(StepValueProperty, value);
this.ViewModel.Step = this.Step;
}
}
public double TextValue
{
get
{
return (double)GetValue(TextValueProperty);
}
set
{
SetValue(TextValueProperty, value);
this.ViewModel.ControlValue = Convert.ToString(value);
}
}
财产的初始化。
static NumericUpDown()
{
MaximumValueProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(null));
MinimumValueProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(null));
StepValueProperty = DependencyProperty.Register("Step", typeof(double), typeof(NumericUpDown), new PropertyMetadata(null));
TextValueProperty = DependencyProperty.Register("TextValue", typeof(double), typeof(NumericUpDown), new PropertyMetadata(null));
}
我在MainPage.xaml页面中的Usercontrol实现如下
<local:NumericUpDown Maximum="28" Minimum="-28" Step="0.25" TextValue="{Binding ElementName=FranePrice, Path=DataContext.FranePrice}"></local:NumericUpDown>
我有另一个ViewModel,它绑定到XAML页面,ViewModel中有一个属性,它绑定到Usercontrol的 TextValue 属性。
FramePrice是View模型中的属性,我绑定到用户控件的TextValue属性
和主页XAML是
<UserControl x:Class="DatePicker.MainPage"
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:local="clr-namespace:DatePicker"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Vertical">
<local:NumericUpDown Maximum="28" Minimum="-28" Step="0.25" TextValue="{Binding ElementName=FranePrice, Path=DataContext.FranePrice}"></local:NumericUpDown>
<Button Content="Show Date" Height="23" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click"/>
</StackPanel>
</Grid>
我使用用户控件的页面的View模型。点击事件我向用户显示TextValue。
公共类MainPageViewModel:EntityViewModel {
public MainPageViewModel()
{
}
private double framePrice;
public Double FramePrice
{
get
{
return framePrice;
}
set
{
framePrice = value;
PropertyChangedHandler("FramePrice");
}
}
}
当我在用户控件中更改TextValue时,它在页面视图模型的FramePrice属性中不会更改。
代码中有什么问题。???
根据 Luke Woodward 的帖子,我更新了以下代码
public static readonly DependencyProperty MaximumValueProperty;
public static readonly DependencyProperty MinimumValueProperty;
public static readonly DependencyProperty StepValueProperty;
public static readonly DependencyProperty TextValueProperty;
public static double Max;
public static double Min;
public static double Stp;
public static double Val;
public double Maximum
{
get
{
return (double)GetValue(MaximumValueProperty);
}
set
{
SetValue(MaximumValueProperty, value);
}
}
public double Minimum
{
get
{
return (double)GetValue(MinimumValueProperty);
}
set
{
SetValue(MinimumValueProperty, value);
}
}
public double Step
{
get
{
return (double)GetValue(StepValueProperty);
}
set
{
SetValue(StepValueProperty, value);
}
}
public double TextValue
{
get
{
return (double)GetValue(TextValueProperty);
}
set
{
SetValue(TextValueProperty, value);
}
}
static NumericUpDown()
{
MaximumValueProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(new PropertyChangedCallback(onMaximumValueChanged)));
MinimumValueProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(new PropertyChangedCallback(onMinimumValueChanged)));
StepValueProperty = DependencyProperty.Register("Step", typeof(double), typeof(NumericUpDown), new PropertyMetadata(new PropertyChangedCallback(onStepValueChanged)));
TextValueProperty = DependencyProperty.Register("TextValue", typeof(double), typeof(NumericUpDown), new PropertyMetadata(new PropertyChangedCallback(onTextValueChanged)));
}
private static void onStepValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Stp = (double)e.NewValue;
}
private static void onMinimumValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Min = (double)e.NewValue;
}
private static void onMaximumValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Max = (double)e.NewValue;
}
private static void onTextValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Val = (double)e.NewValue;
}
然后我在用户控件的视图模型中访问 Max,Min,Stp和Val 属性来执行我的逻辑。
和XAML代码如下
<local:NumericUpDown x:Name="ctlUpDown" Maximum="28" Minimum="-28" Step="0.25" TextValue="{Binding Path=FramePrice}"></local:NumericUpDown>
和用户控制的XAML
<StackPanel Margin="5" Orientation="Horizontal" VerticalAlignment="Center">
<TextBox x:Name="InputTextBox" Grid.Row="0" Grid.Column="0" Grid.RowSpan="1"
Height="23" VerticalAlignment="Top"
Width="50" TextAlignment="Center"
KeyDown="InputTextBox_KeyDown"
KeyUp="InputTextBox_KeyUp"
GotFocus="InputTextBox_GotFocus"
LostFocus="InputTextBox_LostFocus"
MouseWheel="InputTextBox_MouseWheel"
MouseEnter="InputTextBox_MouseEnter"
Text="{Binding Path=TextValue, ElementName=ctlUpDown, Mode=TwoWay,ValidatesOnDataErrors=True,ValidatesOnExceptions=True,NotifyOnValidationError=True}"
/>
</StackPanel>
答案 0 :(得分:1)
我注意到您的代码错误的第一件事是属性Maximum
,Minimum
,Step
和TextValue
。这是TextValue
属性:
public double TextValue
{
get
{
return (double)GetValue(TextValueProperty);
}
set
{
SetValue(TextValueProperty, value);
this.ViewModel.ControlValue = Convert.ToString(value);
}
}
依赖项属性支持的属性(例如上面提到的四个属性)始终应如下所示:
public double TextValue
{
get { return (double)GetValue(TextValueProperty); }
set { SetValue(TextValueProperty, value); }
}
换句话说,getter只包含对GetValue的调用,而setter只包含对SetValue的调用。
原因是当Silverlight更改TextValue依赖项属性的值时,它不会通过使用上面的属性来执行此操作。依赖项属性的值存储在Silverlight依赖关系系统中,当Silverlight想要更改其中一个的值时,它会直接转到此依赖关系系统。它根本不会调用您的代码。上面提供的属性仅为方便起见,为您提供了一种访问和更改依赖项属性中存储的值的简便方法。除了您自己的代码之外,它们永远不会被其他任何东西调用。
通常,如果要在依赖项属性值更改时调用方法,则需要在注册依赖项属性时在PropertyMetadata中传递PropertyChangedCallback。但是,我怀疑在你的情况下你不需要这样做。
在我看来,你有三个属性:
我的印象是,您希望视图模型中的FramePrice属性始终具有与TextBox的Text属性相同的值。为此,您需要将FramePrice属性绑定到NumericUpDown的TextValue属性,然后将其绑定到TextBox的Text属性。
要将这两个属性绑定在一起,有几点需要改变。首先,TextValue
元素中的<local:NumericUpDown>
属性应该类似于
TextValue="{Binding Path=FramePrice}"
绑定{Binding ElementName=FramePrice, Path=DataContext.FramePrice}
不起作用,因为XAML中没有属性x:Name="FramePrice"
的元素。 ElementName
中{Binding ...}
属性的值必须与XAML中对象的x:Name
匹配。
您还需要为主页面设置DataContext。如果您的主页面视图模型对象具有零参数构造函数,则执行此操作的一种方法是遵循this answer。
要将后两个属性绑定在一起,我会:
x:Name
属性添加到NumericUpDown控件的<UserControl>
元素(例如x:Name="ctlUpDown"
),使用以下内容替换NumericUpDown控件中Text
的{{1}}属性:
TextBox
完成后,您可以从代码隐藏类中删除所有行Text="{Binding Path=TextValue, ElementName=ctlUpDown, Mode=TwoWay, ValidatesOnDataErrors=True, ValidatesOnExceptions=True, NotifyOnValidationError=True}"/>
。它们不是必需的,正如我已经解释过的那样,当你想要它们时它们不会被运行。
最后,您是否有理由不使用Silverlight Toolkit的NumericUpDown控件?
编辑2 :根据我更好的判断,我看了一下你上传的两个Silverlight项目之一(我忽略了一个带有_2的项目)。它与你的问题几乎没有相似之处。
我只能假设您希望两个文本框(其中一个在用户控件中)始终具有相同的值。在做出以下更改后,我能够做到这一点:
MainPageViewModel.cs:将this.ViewModel.SomeProperty = ...
添加到属性设置器。 (否则验证错误永远不会被清除。)
MyUserControlWVM.xaml:删除了对ClearErrorFromProperty("DPropertyBind");
事件处理程序的引用,在Text属性上添加了绑定,并向LostFocus
元素添加了添加x:Name
属性。换句话说,现在看起来如下:
<UserControl>
MyUserControlWVM.xaml.cs:将依赖项属性<UserControl x:Class="DependencyPropertyBinding.MyUserControlWVM"
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"
mc:Ignorable="d"
x:Name="ctlWVM"
d:DesignHeight="300" d:DesignWidth="205">
<StackPanel Orientation="Horizontal" Width="204" Height="32">
<TextBox x:Name="textbox" Height="30" Width="200" Text="{Binding Path=DProperty, ElementName=ctlWVM, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
</StackPanel>
</UserControl>
重命名为DependencyPropertyValue
(命名约定是DPropertyProperty
字段具有属性的名称(在本例中为{附加static readonly
的{1}})。我还删除了DProperty
事件处理程序。
答案 1 :(得分:0)
如果上面的代码是准确的,那么您已将 FramePrice 拼写为绑定中的 FranePrice
输出页面应该在加载页面时将其显示为绑定错误。
目前
Binding ElementName=FranePrice, Path=DataContext.FranePrice
应该是:
Binding ElementName=FramePrice, Path=DataContext.FramePrice
“具有强大的绑定功能带来了很大的责任”:)