WPF 用户控件与 MVVM ViewModel 的数据绑定

WPF Usercontrol databinding with MVVM ViewModel

我在这上面花了很多时间所以寻求帮助。

使用 mvvm light 与用户控件的简单数据绑定不起作用。

我已经完成了以下操作。

  1. 使用 VS 2015 创建了一个 MvvmLight (WPF451) 项目并将其命名为 WpfDataBindingUserControlT1
  2. 添加了一个 UserControl 并将其重命名为 SimpleUserControl.xaml
  3. 将一些标签作为子标签(包裹在堆栈面板中)添加到内部网格 SimpleUserControl.xaml(所有代码在下面给出)
  4. 在 SimpleUserControl.xaml(SimpleUserControl.cs) 的代码后面添加了一个依赖属性,以便这些将帮助我进行数据绑定。

数据绑定根本不起作用。我已经为此拉了一半头发,所以请帮忙。我想我在这方面很简单。

代码如下

  1. MainWindows.xaml

    <Window x:Class="WpfDataBindingUserControlT1.MainWindow"
            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:ignore="http://www.galasoft.ch/ignore"
            xmlns:local="clr-namespace:WpfDataBindingUserControlT1"
            mc:Ignorable="d ignore"
            Height="400"
            Width="300"
            Title="MVVM Light Application"
            DataContext="{Binding Main, Source={StaticResource Locator}}">
    
        <Window.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Skins/MainSkin.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Window.Resources>
    
        <Grid x:Name="LayoutRoot">
    
            <TextBlock FontSize="36"
                       FontWeight="Bold"
                       Foreground="Purple"
                       Text="{Binding WelcomeTitle}"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       TextWrapping="Wrap" />
    
            <local:SimpleUserControl DataContext="{Binding RelativeSource={RelativeSource Self}}" CellValue="{Binding WelcomeTitle}" />
        </Grid>
    </Window>
    
  2. MainWindow.cs(我没有更改此文件中的任何内容。)

    using System.Windows;
    using WpfDataBindingUserControlT1.ViewModel;
    
    namespace WpfDataBindingUserControlT1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            /// <summary>
            /// Initializes a new instance of the MainWindow class.
            /// </summary>
            public MainWindow()
            {
                InitializeComponent();
                Closing += (s, e) => ViewModelLocator.Cleanup();
            }
        }
    }
    
  3. SimpleUserControl.xaml

    <UserControl x:Class="WpfDataBindingUserControlT1.SimpleUserControl"
                 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:WpfDataBindingUserControlT1"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
            <StackPanel>
                <Label Content="This Prints" />
                <Label Name="MyLable" Content="{Binding Path=CellValue}"></Label>
                <Label Content="This also Prints" />
            </StackPanel>
        </Grid>
    </UserControl>
    
  4. SimpleUserControl.cs(添加了依赖项)

    using System.Windows;
    using System.Windows.Controls;
    
    namespace WpfDataBindingUserControlT1
    {
        /// <summary>
        /// Interaction logic for SimpleUserControl.xaml
        /// </summary>
        public partial class SimpleUserControl : UserControl
        {
            public string CellValue
            {
                get { return (string)GetValue(CellValueProperty); }
                set { SetValue(CellValueProperty, value); }
            }
    
            public static readonly DependencyProperty CellValueProperty = 
                DependencyProperty.Register("CellValue", typeof(string), typeof(SimpleUserControl), new FrameworkPropertyMetadata
                {
                    BindsTwoWayByDefault = true,
                });
    
            public SimpleUserControl()
            {
                InitializeComponent();
            }
        }
    }
    
  5. MainViewModel.cs(这里我没有做任何改动)

    using GalaSoft.MvvmLight;
    using WpfDataBindingUserControlT1.Model;
    
    namespace WpfDataBindingUserControlT1.ViewModel
    {
        /// <summary>
        /// This class contains properties that the main View can data bind to.
        /// <para>
        /// See http://www.mvvmlight.net
        /// </para>
        /// </summary>
        public class MainViewModel : ViewModelBase
        {
            private readonly IDataService _dataService;
    
            /// <summary>
            /// The <see cref="WelcomeTitle" /> property's name.
            /// </summary>
            public const string WelcomeTitlePropertyName = "WelcomeTitle";
    
            private string _welcomeTitle = string.Empty;
    
            /// <summary>
            /// Gets the WelcomeTitle property.
            /// Changes to that property's value raise the PropertyChanged event. 
            /// </summary>
            public string WelcomeTitle
            {
                get
                {
                    return _welcomeTitle;
                }
                set
                {
                    Set(ref _welcomeTitle, value);
                }
            }
    
            /// <summary>
            /// Initializes a new instance of the MainViewModel class.
            /// </summary>
            public MainViewModel(IDataService dataService)
            {
                _dataService = dataService;
                _dataService.GetData(
                    (item, error) =>
                    {
                        if (error != null)
                        {
                            // Report error here
                            return;
                        }
    
                        WelcomeTitle = item.Title;
                    });
            }
    
            ////public override void Cleanup()
            ////{
            ////    // Clean up if needed
    
            ////    base.Cleanup();
            ////}
        }
    }
    
  6. ViewModelLocator.cs(我也没有改变任何东西。)

    /*
      In App.xaml:
      <Application.Resources>
          <vm:ViewModelLocatorTemplate xmlns:vm="clr-namespace:WpfDataBindingUserControlT1.ViewModel"
                                       x:Key="Locator" />
      </Application.Resources>
    
      In the View:
      DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
    */
    
    using GalaSoft.MvvmLight;
    using GalaSoft.MvvmLight.Ioc;
    using Microsoft.Practices.ServiceLocation;
    using WpfDataBindingUserControlT1.Model;
    
    namespace WpfDataBindingUserControlT1.ViewModel
    {
        /// <summary>
        /// This class contains static references to all the view models in the
        /// application and provides an entry point for the bindings.
        /// <para>
        /// See http://www.mvvmlight.net
        /// </para>
        /// </summary>
        public class ViewModelLocator
        {
            static ViewModelLocator()
            {
                ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
    
                if (ViewModelBase.IsInDesignModeStatic)
                {
                    SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
                }
                else
                {
                    SimpleIoc.Default.Register<IDataService, DataService>();
                }
    
                SimpleIoc.Default.Register<MainViewModel>();
            }
    
            /// <summary>
            /// Gets the Main property.
            /// </summary>
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
                "CA1822:MarkMembersAsStatic",
                Justification = "This non-static member is needed for data binding purposes.")]
            public MainViewModel Main
            {
                get
                {
                    return ServiceLocator.Current.GetInstance<MainViewModel>();
                }
            }
    
            /// <summary>
            /// Cleans up all the resources.
            /// </summary>
            public static void Cleanup()
            {
            }
        }
    }
    

将此行添加到您的 SimpleUserControl.cs 构造函数

public SimpleUserControl()
{
    InitializeComponent();

    (this.Content as FrameworkElement).DataContext = this;
}    

您基本上是在 UserControl 中设置第一个元素的 DataContext

Jerry Nixon 在这方面有一篇很棒的文章 here

更新 忘记添加去掉 RelativeSource eg

<local:SimpleUserControl CellValue="{Binding WelcomeTitle}" />