C# 使用WPF、MVVM和DP的用户控制
我正在尝试设计一个UserControl,特别是NumericUpDownControlC# 使用WPF、MVVM和DP的用户控制,c#,wpf,mvvm,dependency-properties,C#,Wpf,Mvvm,Dependency Properties,我正在尝试设计一个UserControl,特别是NumericUpDownControl <UserControl x:Class="SettingsDialog.Controls.NumericUpDownControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winf
<UserControl x:Class="SettingsDialog.Controls.NumericUpDownControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SettingsDialog.Controls"
xmlns:viewModels="clr-namespace:SettingsDialog.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="18"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Text="{Binding Value}" Grid.Row="0" Grid.RowSpan="2" Height="20" VerticalContentAlignment="Center"/>
<RepeatButton Content="5" Grid.Column="1" Grid.Row="0" FontSize="8" Height="10" FontFamily="Marlett" VerticalContentAlignment="Center"/>
<RepeatButton Content="6" Grid.Column="1" Grid.Row="1" FontSize="8" Height="10" FontFamily="Marlett" VerticalContentAlignment="Center"/>
</Grid>
</UserControl>
它工作正常,因为我可以在MainWindow.xaml中使用它,如下所示:
<controls:NumericUpDownControl Width="100" Value="10"/>
但问题是我还需要一个ViewModel作为我的UserControl。当我设置它时,UserControl中的
文本框
就不再识别值
依赖属性。如何在拥有ViewModel的同时从用户控件外部设置值
?我做错了什么吗?不能同时将UserControl绑定到自身和ViewModel
您必须从UserControl中删除
DataContext=“{Binding RelativeSource={RelativeSource Self}}}”
,并确保在将UserControl集成到UI中时将正确的DataContext
传递给UserControl。不能同时将UserControl绑定到自身和ViewModel
您必须删除
DataContext=“{Binding RelativeSource={RelativeSource Self}”
从用户控件内部,并确保在将其集成到UI中时将正确的数据上下文
传递给用户控件。这应将文本框
的文本
属性绑定到用户控件
的值
属性,而不管其数据上下文
:
<TextBox Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}" Grid.Row="0" Grid.RowSpan="2" Height="20" VerticalContentAlignment="Center"/>
这应该将
文本框的文本
属性绑定到用户控件的值
属性,而不管其数据上下文
:
<TextBox Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}" Grid.Row="0" Grid.RowSpan="2" Height="20" VerticalContentAlignment="Center"/>
由于您正在创建一种自定义控件,解决问题的另一种方法是使用依赖项属性的propertychanged回调,每次它发生更改时,您只需更新Textbox的文本属性:
public partial class NumericUpDownControl : UserControl
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int),typeof(NumericUpDownControl),new PropertyMetadata(OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((NumericUpDownControl) d).TextBox.Text = e.NewValue?.ToString() ?? string.Empty;
}
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public NumericUpDownControl()
{
InitializeComponent();
}
}
}
由于您正在创建一种自定义控件,解决问题的另一种方法是简单地使用dependency属性的propertychanged回调,每次它更改时,您只需更新Textbox的Text属性:
public partial class NumericUpDownControl : UserControl
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(int),typeof(NumericUpDownControl),new PropertyMetadata(OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((NumericUpDownControl) d).TextBox.Text = e.NewValue?.ToString() ?? string.Empty;
}
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public NumericUpDownControl()
{
InitializeComponent();
}
}
}
在UserControl的构造函数中,add DataContext=this@NawedNabiZada我希望UserControl也有一个ViewModel,然后将其设置为var myViewModel=new myViewModel();myViewModel.Value=此.Value;数据上下文=myViewModel@NawedNabiZada谢谢,这很有道理!我很好奇这是否是最好的解决方案!因为如果将其传递给ViewModel并稍后在ViewModel中更改,它将不会反映在Dependency属性中@Vahid将
视为通用用例。无论何时将MyViewModel实例传递给ContentControl或ContentPresenter(也在ItemsControl中),DataTemplate都会实例化MyUserControl并将MyViewModel实例传递给其DataContext@NawedNabiZada我希望UserControl也有一个ViewModel,然后将其设置为var myViewModel=new myViewModel();myViewModel.Value=此.Value;数据上下文=myViewModel@NawedNabiZada谢谢,这很有道理!我很好奇这是否是最好的解决方案!因为如果将其传递给ViewModel并稍后在ViewModel中更改,它将不会反映在Dependency属性中@Vahid将
视为通用用例。无论何时将MyViewModel的实例传递给ContentControl或ContentPresenter(也在ItemsControl中),DataTemplate都会实例化MyUserControl,并将MyViewModel实例传递给其DataContext。感谢您的帮助。我在设计用户控件方面做得对吗?还是有更好更标准的方法?这取决于。一般来说,UserControl应该继承DataContext,您不应该显式地设置它的DataContext属性。但是,例如文本框本身不是控件吗?你是在暗示它在代码背后没有自己的视图模型,尽管它对我们来说是隐藏的吗?文本框是一个控件,它当然没有视图模型。谢谢你的工作。我在设计用户控件方面做得对吗?还是有更好更标准的方法?这取决于。一般来说,UserControl应该继承DataContext,您不应该显式地设置它的DataContext属性。但是,例如文本框本身不是控件吗?你是在暗示它在代码背后没有自己的视图模型,尽管它对我们是隐藏的吗?文本框是一个控件,它当然没有视图模型。