WPF Usercontrol与MVVM ViewModel的数据绑定

时间:2016-05-04 11:06:39

标签: wpf xaml mvvm data-binding user-controls

我花了很长时间才寻求帮助。

使用mvvm light与usercontrol进行简单数据绑定不起作用。

我做了以下事情。

  1. 使用VS 2015创建了一个MvvmLight(WPF451)项目,并将其命名为WpfDataBindingUserControlT1
  2. 添加了UserControl并将其重命名为SimpleUserControl.xaml
  3. 在SimpleUserControl.xaml中向网格添加了一些作为子项(包含在stackpanel中)的标签(所有代码如下)
  4. 在SimpleUserControl.xaml(SimpleUserControl.cs)后面的代码中添加了依赖项属性,以便这些可以帮助我进行数据绑定。
  5. 数据绑定根本不起作用。我已经拉了一半头发,所以请帮忙。我想我在这方面很缺失。

    代码如下。

    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()
              {
              }
          }
      }
      

1 个答案:

答案 0 :(得分:3)

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

public SimpleUserControl()
{
    InitializeComponent();

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

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

Jerry Nixon在这篇here

上有一篇很棒的文章

<强>更新 忘了添加摆脱RelativeSource例如

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