Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Data binding with ResourceDictionary MVVM

Tags:

c#

mvvm

binding

wpf

I'm trying to bind a View with a ViewModel within ResourceDictionary but it does not work.

The application is very simple window with 2 textboxes. When I type text to textbox1, atutomatically, textbox2 must get the same text. Of course my textboxes from the View have to be binded to my properties in ViewModel.

I'm new to WPF and the way I started to bind Views and ViewModels was in the codebehind of a View:

DataContext = new MyViewModel();

Now I'm trying to achieve a cleaner separation. My code is

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:

<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:

<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:

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:

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

        }
    }

And implemened the INotifyPropertyChanged like this:

public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(String propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
like image 623
shadox Avatar asked Dec 31 '12 13:12

shadox


2 Answers

so user1064519 was on the right track:

  • the View needs to be a UserControl, not a Window, as it is hosted in the MainWindow
  • the ViewModel needs to be loaded into the MainWindow, this is what triggers the DataTemplate to be discovered and loaded.

    <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

like image 113
TheZenker Avatar answered Sep 30 '22 15:09

TheZenker


DataTemplate sholudnt contain window, it can contains any kind of control.

DataTemplate :

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

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>
like image 24
user1064519 Avatar answered Sep 30 '22 15:09

user1064519