Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.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# 窗口中的ViewModel和UserControl中的ViewModel之间的WPF数据绑定_C#_Wpf_Xaml_Mvvm_Data Binding - Fatal编程技术网

C# 窗口中的ViewModel和UserControl中的ViewModel之间的WPF数据绑定

C# 窗口中的ViewModel和UserControl中的ViewModel之间的WPF数据绑定,c#,wpf,xaml,mvvm,data-binding,C#,Wpf,Xaml,Mvvm,Data Binding,我在这个窗口中使用了一个窗口和一个usercontrol 我已经做了以下工作: 将窗口属性绑定到窗口的viewmodel属性 将usercontrol属性绑定到usercontrol的viewmodel属性 将usercontrol属性绑定到窗口的viewmodel属性 在我看来,我认为如果按特定值设置window属性,usercontrol的viewmodel属性将设置为相同的值 但是usercontrol的viewmodel属性没有设置为相同的值 这是完整的代码 MainWindow.xam

我在这个窗口中使用了一个窗口和一个usercontrol

我已经做了以下工作:

  • 将窗口属性绑定到窗口的viewmodel属性
  • 将usercontrol属性绑定到usercontrol的viewmodel属性
  • 将usercontrol属性绑定到窗口的viewmodel属性
  • 在我看来,我认为如果按特定值设置window属性,usercontrol的viewmodel属性将设置为相同的值

    但是usercontrol的viewmodel属性没有设置为相同的值

    这是完整的代码

    MainWindow.xaml.cs

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Window1 w = new Window1();
                w.Mode = RegisterMode.Update;
                w.Show();
            }
        }
    
    Window1.xaml

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MVVMTest2" x:Name="window" x:Class="MVVMTest2.Window1"
            Title="Window1" Height="300" Width="300">
        <Window.DataContext>
            <local:WindowViewModel></local:WindowViewModel>
        </Window.DataContext>
        <Grid>
            <local:UserControl1 x:Name="uc1" HorizontalAlignment="Left" Height="100" Margin="77,116,0,0" VerticalAlignment="Top" Width="100" Mode="{Binding DataContext.Mode, ElementName=window, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <Button Content="Button" HorizontalAlignment="Left" Margin="156,43,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        </Grid>
    </Window>
    
    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MVVMTest2" x:Name="window" x:Class="MVVMTest2.Window1"
            Title="Window1" Height="300" Width="300"
            Mode={Binding UcViewModel.Mode}> <!-- Added this binding -->
    
        <!-- MOVED THIS TO THE CODE-BEHIND
        <Window.DataContext>
            <local:WindowViewModel></local:WindowViewModel>
        </Window.DataContext>
        -->
    
        <Grid>
            <local:UserControl1 x:Name="uc1" HorizontalAlignment="Left" Height="100" Margin="77,116,0,0" VerticalAlignment="Top" Width="100" 
                                Mode="{Binding UcViewModel.Mode}"/>
            <Button Content="Button" HorizontalAlignment="Left" Margin="156,43,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        </Grid>
    </Window>
    
    WindowViewModel.cs

        public class WindowViewModel : INotifyPropertyChanged
        {
            RegisterMode mode = RegisterMode.None;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public RegisterMode Mode
            {
                get { return this.mode; }
                set
                {
                    this.mode = value;
                    RaisePropertyChanged("Mode");
                }
            }
    
            void RaisePropertyChanged(string propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
        public class UCViewModel : INotifyPropertyChanged
        {
            RegisterMode mode = RegisterMode.None;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public RegisterMode Mode
            {
                get { return this.mode; }
                set
                {
                    this.mode = value;
                    RaisePropertyChanged("Mode");
                }
            }
    
            void RaisePropertyChanged(string propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));                
                }
            }
        }
    
    public class WindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        /* Remove this:
        RegisterMode mode = RegisterMode.None;
        public RegisterMode Mode
        {
            get { return this.mode; }
            set
            {
                this.mode = value;
                RaisePropertyChanged("Mode");
            }
        }
        */
    
        // Use composition instead
        UCViewModel _ucViewModel = null;
        public UCViewModel UcViewModel
        {
            get 
            { 
                if (_ucViewModel == null)
                {
                    _ucViewModel = new UCViewModel();
                }
                return _ucViewModel; 
            }
        }
    
        void RaisePropertyChanged(string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    
    UserControl1.xaml

    <UserControl x:Class="MVVMTest2.UserControl1"
                 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:MVVMTest2"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <UserControl.DataContext>
            <local:UCViewModel></local:UCViewModel>
        </UserControl.DataContext>
        <Grid>
    
        </Grid>
    </UserControl>
    
    <UserControl x:Class="MVVMTest2.UserControl1"
                 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:MVVMTest2"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
    
    <!-- THIS PART IS NOT NEEDED
         <UserControl.DataContext>
            <local:UCViewModel></local:UCViewModel>
        </UserControl.DataContext>
     -->
        <Grid>
    
        </Grid>
    </UserControl>
    
    UCViewModel.cs

        public class WindowViewModel : INotifyPropertyChanged
        {
            RegisterMode mode = RegisterMode.None;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public RegisterMode Mode
            {
                get { return this.mode; }
                set
                {
                    this.mode = value;
                    RaisePropertyChanged("Mode");
                }
            }
    
            void RaisePropertyChanged(string propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
        public class UCViewModel : INotifyPropertyChanged
        {
            RegisterMode mode = RegisterMode.None;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public RegisterMode Mode
            {
                get { return this.mode; }
                set
                {
                    this.mode = value;
                    RaisePropertyChanged("Mode");
                }
            }
    
            void RaisePropertyChanged(string propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));                
                }
            }
        }
    
    public class WindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        /* Remove this:
        RegisterMode mode = RegisterMode.None;
        public RegisterMode Mode
        {
            get { return this.mode; }
            set
            {
                this.mode = value;
                RaisePropertyChanged("Mode");
            }
        }
        */
    
        // Use composition instead
        UCViewModel _ucViewModel = null;
        public UCViewModel UcViewModel
        {
            get 
            { 
                if (_ucViewModel == null)
                {
                    _ucViewModel = new UCViewModel();
                }
                return _ucViewModel; 
            }
        }
    
        void RaisePropertyChanged(string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    
    我做错了什么?
    请让我知道。

    使用您的
    视图模型之间的组合尝试此解决方案

    Window1.xaml

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MVVMTest2" x:Name="window" x:Class="MVVMTest2.Window1"
            Title="Window1" Height="300" Width="300">
        <Window.DataContext>
            <local:WindowViewModel></local:WindowViewModel>
        </Window.DataContext>
        <Grid>
            <local:UserControl1 x:Name="uc1" HorizontalAlignment="Left" Height="100" Margin="77,116,0,0" VerticalAlignment="Top" Width="100" Mode="{Binding DataContext.Mode, ElementName=window, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            <Button Content="Button" HorizontalAlignment="Left" Margin="156,43,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        </Grid>
    </Window>
    
    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MVVMTest2" x:Name="window" x:Class="MVVMTest2.Window1"
            Title="Window1" Height="300" Width="300"
            Mode={Binding UcViewModel.Mode}> <!-- Added this binding -->
    
        <!-- MOVED THIS TO THE CODE-BEHIND
        <Window.DataContext>
            <local:WindowViewModel></local:WindowViewModel>
        </Window.DataContext>
        -->
    
        <Grid>
            <local:UserControl1 x:Name="uc1" HorizontalAlignment="Left" Height="100" Margin="77,116,0,0" VerticalAlignment="Top" Width="100" 
                                Mode="{Binding UcViewModel.Mode}"/>
            <Button Content="Button" HorizontalAlignment="Left" Margin="156,43,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
        </Grid>
    </Window>
    
    UserControl1.xaml

    <UserControl x:Class="MVVMTest2.UserControl1"
                 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:MVVMTest2"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <UserControl.DataContext>
            <local:UCViewModel></local:UCViewModel>
        </UserControl.DataContext>
        <Grid>
    
        </Grid>
    </UserControl>
    
    <UserControl x:Class="MVVMTest2.UserControl1"
                 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:MVVMTest2"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
    
    <!-- THIS PART IS NOT NEEDED
         <UserControl.DataContext>
            <local:UCViewModel></local:UCViewModel>
        </UserControl.DataContext>
     -->
        <Grid>
    
        </Grid>
    </UserControl>
    
    WindowViewModel.cs

        public class WindowViewModel : INotifyPropertyChanged
        {
            RegisterMode mode = RegisterMode.None;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public RegisterMode Mode
            {
                get { return this.mode; }
                set
                {
                    this.mode = value;
                    RaisePropertyChanged("Mode");
                }
            }
    
            void RaisePropertyChanged(string propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    
        public class UCViewModel : INotifyPropertyChanged
        {
            RegisterMode mode = RegisterMode.None;
            public event PropertyChangedEventHandler PropertyChanged;
    
            public RegisterMode Mode
            {
                get { return this.mode; }
                set
                {
                    this.mode = value;
                    RaisePropertyChanged("Mode");
                }
            }
    
            void RaisePropertyChanged(string propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));                
                }
            }
        }
    
    public class WindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        /* Remove this:
        RegisterMode mode = RegisterMode.None;
        public RegisterMode Mode
        {
            get { return this.mode; }
            set
            {
                this.mode = value;
                RaisePropertyChanged("Mode");
            }
        }
        */
    
        // Use composition instead
        UCViewModel _ucViewModel = null;
        public UCViewModel UcViewModel
        {
            get 
            { 
                if (_ucViewModel == null)
                {
                    _ucViewModel = new UCViewModel();
                }
                return _ucViewModel; 
            }
        }
    
        void RaisePropertyChanged(string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    
    还有一件事,您可能希望将ViewModel属性
    Mode
    重命名为另一个名称,如
    RegMode
    。原因是绑定过程中XAML代码会让人困惑

    由此:
    {绑定模式,模式=双向}
    或者,这是:
    {绑定路径=模式,模式=双向}
    对于这个不那么令人困惑的问题:
    {Binding RegMode,Mode=TwoWay}

    您不应该显式设置UserControl的DataContext,因为这样做可以有效地防止DataContext从UserControl的父项继承。请参见此处示例:@Clemens那么如何更改构造函数中的绑定代码?请给我看一些东西。UserControl和Window1的构造函数中不应该有任何绑定代码。相反,当声明它们的实例时,它们的属性应该在XAML中绑定,例如
    。绑定源将是从窗口继承的DataContext。@YHKim我只是想澄清一下您希望发生什么,您希望UCViewModel.Mode获得WindowViewModel.Mode中设置的值?@janonimus我想将模式值从Window1发送到UCViewModel。So MessageBox.Show((uc1.DataContext作为UCViewModel.Mode.ToString());应显示“更新”。感谢您的回答。这接近我想要的。