Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用WPF、MVVM和DP的用户控制_C#_Wpf_Mvvm_Dependency Properties - Fatal编程技术网

C# 使用WPF、MVVM和DP的用户控制

C# 使用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,特别是NumericUpDownControl

<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属性。但是,例如文本框本身不是控件吗?你是在暗示它在代码背后没有自己的视图模型,尽管它对我们是隐藏的吗?文本框是一个控件,它当然没有视图模型。