简体   繁体   English

与ResourceDictionary MVVM的WPF数据绑定

[英]WPF Data binding with ResourceDictionary MVVM

I'm trying to bind a View with a ViewModel within ResourceDictionary but it does not work. 我正在尝试将View与ViewDode中的ViewModel绑定,但它不起作用。

The application is very simple window with 2 textboxes. 该应用程序是非常简单的窗口,有2个文本框。 When I type text to textbox1, atutomatically, textbox2 must get the same text. 当我在textbox1中输入文本时,textbox2必须自动获取相同的文本。 Of course my textboxes from the View have to be binded to my properties in ViewModel. 当然,View中的文本框必须绑定到ViewModel中的属性。

I'm new to WPF and the way I started to bind Views and ViewModels was in the codebehind of a View: 我是WPF的新手,我开始绑定Views和ViewModels的方式是在View的代码隐藏中:

DataContext = new MyViewModel();

Now I'm trying to achieve a cleaner separation. 现在我正在努力实现更清洁的分离。 My code is 我的代码是

App.xaml: App.xaml中:

<Application x:Class="NavigationCleanBinding.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="/Views/MainWindowView.xaml">
    <Application.Resources>
        <ResourceDictionary Source="MainResourceDictionary.xaml" />
    </Application.Resources>
</Application>

MainResourceDictionary.xaml: MainResourceDictionary.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xamlpresentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Views="clr-namespace:NavigationCleanBinding.Views"
    xmlns:ViewModels="clr-namespace:NavigationCleanBinding.ViewModels">

    <DataTemplate DataType="{x:Type ViewModels:MainWindowViewModel}">
        <Views:MainWindowView />
    </DataTemplate>

</ResourceDictionary>

MainWindowView.xaml: MainWindowView.xaml:

<Window x:Class="NavigationCleanBinding.Views.MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<Grid>
    <TextBox Height="23" HorizontalAlignment="Left" Margin="61,14,0,0" 
             Name="textBox1" VerticalAlignment="Top" Width="120" 
             Text="{Binding TestData, Mode=TwoWay,
             UpdateSourceTrigger=PropertyChanged}"/>
    <Label Content="Test:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0"
      Name="label1" VerticalAlignment="Top" Width="43" />
    <Label Content="Result:" Height="28" HorizontalAlignment="Left" Margin="10,46,0,0"
      Name="label2" VerticalAlignment="Top" />

    <TextBox Height="23" HorizontalAlignment="Left" Margin="61,48,0,0"
             Name="textBox2" VerticalAlignment="Top" Width="120" 

             Text="{Binding TestData, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</Window>

MainWindowViewModel: MainWindowViewModel:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NavigationCleanBinding.ViewModels
{
    class MainWindowViewModel
    {
        private String _testData;
        public String TestData
        {
            get { return _testData; }
            set { _testData = value; }
        }

        private MainWindowViewModel()
        {
            _testData = null;
        }
    }
}

UPDATE: 更新:

I changed property TestData to this: 我将属性TestData更改为:

public String TestData
    {
        get { return _testData; }
        set
        { 
            _testData = value;
            OnPropertyChanged("TestData");

        }
    }

And implemened the INotifyPropertyChanged like this: 并实现了这样的INotifyPropertyChanged:

public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

so user1064519 was on the right track: 所以user1064519走在正确的轨道上:

  • the View needs to be a UserControl , not a Window , as it is hosted in the MainWindow View必须是UserControl ,而不是Window ,因为它在MainWindow中托管
  • the ViewModel needs to be loaded into the MainWindow, this is what triggers the DataTemplate to be discovered and loaded. 需要将ViewModel加载到MainWindow中,这是触发DataTemplate被发现和加载的原因。

     <Window x:Class="WpfTemplateBootstrap.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfTemplateBootstrap" Title="MainWindow" Height="350" Width="525"> <ContentControl> <ContentControl.Content> <local:MainWindowViewModel /> </ContentControl.Content> </ContentControl> 

After that you should be up and running. 在那之后你应该开始运行。 I have posted an in-depth example here: wpf bootstrapping datatemplates--the chicken and the egg 我在这里发布了一个深入的例子: wpf bootstrapping datatemplates - 鸡肉和鸡蛋

您的ViewModel必须实现接口INotifyPropertyChanged并在任何绑定属性值更改时引发PropertyChanged事件,以便您的视图可以知道发生了更改。

DataTemplate sholudnt contain window, it can contains any kind of control. DataTemplate sholudnt包含窗口,它可以包含任何类型的控件。

DataTemplate : DataTemplate:

 <DataTemplate DataType="{x:Type ViewModels:MainWindowViewModel}">
        <Views:MainWindowView />
 </DataTemplate>

UserControl : UserControl:

    <UserControl x:Class="NavigationCleanBinding.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="350" Width="525">

<Grid>
    <TextBox Height="23" HorizontalAlignment="Left" Margin="61,14,0,0" 
             Name="textBox1" VerticalAlignment="Top" Width="120" 
             Text="{Binding TestData, Mode=TwoWay,
             UpdateSourceTrigger=PropertyChanged}"/>
    <Label Content="Test:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0"
      Name="label1" VerticalAlignment="Top" Width="43" />
    <Label Content="Result:" Height="28" HorizontalAlignment="Left" Margin="10,46,0,0"
      Name="label2" VerticalAlignment="Top" />

    <TextBox Height="23" HorizontalAlignment="Left" Margin="61,48,0,0"
             Name="textBox2" VerticalAlignment="Top" Width="120" 

             Text="{Binding TestData, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</UserControl>

Window : 窗口:

 <Window x:Class="NavigationCleanBinding.Views.MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

<ContentControl Content={Binding}/>
</Window>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM