WPF 用户控件与 MVVM ViewModel 的数据绑定
WPF Usercontrol databinding with MVVM ViewModel
我在这上面花了很多时间所以寻求帮助。
使用 mvvm light 与用户控件的简单数据绑定不起作用。
我已经完成了以下操作。
- 使用 VS 2015 创建了一个 MvvmLight (WPF451) 项目并将其命名为 WpfDataBindingUserControlT1
- 添加了一个 UserControl 并将其重命名为 SimpleUserControl.xaml
- 将一些标签作为子标签(包裹在堆栈面板中)添加到内部网格 SimpleUserControl.xaml(所有代码在下面给出)
- 在 SimpleUserControl.xaml(SimpleUserControl.cs) 的代码后面添加了一个依赖属性,以便这些将帮助我进行数据绑定。
数据绑定根本不起作用。我已经为此拉了一半头发,所以请帮忙。我想我在这方面很简单。
代码如下
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>
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();
}
}
}
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>
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();
}
}
}
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();
////}
}
}
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}" />
我在这上面花了很多时间所以寻求帮助。
使用 mvvm light 与用户控件的简单数据绑定不起作用。
我已经完成了以下操作。
- 使用 VS 2015 创建了一个 MvvmLight (WPF451) 项目并将其命名为 WpfDataBindingUserControlT1
- 添加了一个 UserControl 并将其重命名为 SimpleUserControl.xaml
- 将一些标签作为子标签(包裹在堆栈面板中)添加到内部网格 SimpleUserControl.xaml(所有代码在下面给出)
- 在 SimpleUserControl.xaml(SimpleUserControl.cs) 的代码后面添加了一个依赖属性,以便这些将帮助我进行数据绑定。
数据绑定根本不起作用。我已经为此拉了一半头发,所以请帮忙。我想我在这方面很简单。
代码如下
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>
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(); } } }
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>
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(); } } }
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(); ////} } }
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}" />