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

标签 wpf xaml mvvm data-binding user-controls

我在这方面花了相当长的时间,所以寻求帮助。

使用 mvvm light 与用户控件进行简单数据绑定(bind)不起作用。

我已经完成了以下操作。

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

数据绑定(bind)根本不起作用。我已经拉了一半的头发了,所以请帮忙。我想我在这一点上很简单。

代码如下。

  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 例如

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

关于WPF 用户控件与 MVVM ViewModel 的数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37026023/

相关文章:

wpf - 根据列表框中数据库中的记录动态添加行 mvvm mvvm light

c# - WPF工具栏在调整大小时消失

c# - "Two-way binding requires Path or XPath"编辑 wpf 数据网格时

c# - 如何在 WPF 中播放 Youtube 视频

visual-studio-2010 - 在 Visual Studio 2010 中反复丢失 XAML 智能感知

swift - 无法将 'SharedSequence<DriverSharingStrategy, Data?>'类型的值转换为预期的参数类型

c# - 未调用 PropertyChangedCallback

c# - ScrollTo 无法在 Xamarin.Forms 中使用分组的 ListView

wpf - ViewModel 中的 DependencyProperty 注册

c# - Wpf gridview 选定项