2012-12-31 13 views
5

Próbuję powiązać widok z ViewModel w ResourceDictionary, ale to nie działa.Powiązanie danych WPF z ResourceDictionary MVVM

Aplikacja jest bardzo prostym oknem z 2 polami tekstowymi. Kiedy wpisuję tekst do textbox1, atutomatycznie, textbox2 musi mieć ten sam tekst. Oczywiście moje pola tekstowe z widoku muszą być powiązane z moimi właściwościami w ViewModel.

Jestem nowym do WPF i sposób zacząłem wiązać widoków i ViewModels był w kodzie z widoku:

DataContext = new MyViewModel(); 

Teraz próbuję osiągnąć czystsze separacji. Mój kod jest

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:

Zmieniłem testdata własności do tego:

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

     } 
    } 

I implemened z INotifyPropertyChanged tak:

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

Czy otrzymujesz jakieś błędy w oknie wyjściowym? – Thelonias

+0

Brak błędów, brak ostrzeżeń. To po prostu nie działa. – shadox

+0

Nie sądzę, twój DataContext jest ustawiony dla twojego 'MainWindowView'. Myślę, że zamiast tego 'MainWindowViewModel' jest DataContext dla' MainResourceDictionary'. Ponieważ masz zestaw StartupURI ustawiony na MainWindowView, utworzy on instancję twojego okna, ale nigdy nie ustawi DataContext. Nie jestem pozytywny, ale nie sądzę, że twój ResourceDictionary coś robi w tym momencie. – Thelonias

Odpowiedz

4

tak user1064 519 był na właściwej drodze:

  • View musi być UserControl, a nie Window, ponieważ jest obsługiwany w MainWindow
  • ViewModel musi być załadowany do MainWindow, jest to, co wywołuje the DataTemplate do odkrycia i załadowania.

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

Po tym powinien być uruchomiony. Zamieszczam dogłębny przykład tutaj: wpf bootstrapping datatemplates--the chicken and the egg

+0

Myślę, że TheZenker bardzo dobrze reaguje na swoim blogu, który jest tutaj połączony. – shadox

1

Twój ViewModel musi implementować interfejs INotifyPropertyChanged i podnieść zdarzenie PropertyChanged gdy jest dowolna wartość powiązanej właściwości zmieni się, dzięki czemu Twój widok będzie wiedział, że zmiany nastąpiły.

+0

To nadal nie działa ... mój przyjaciel zasugerował określenie RelativeSource ... czegoś o przodkach ... którego właściwie nie rozumiem. – shadox

1

DataTemplate sholudnt zawiera okno, może zawierać dowolny rodzaj kontroli.

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> 

Okno:

<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> 
+0

Właściwie to nie działa ... czy możesz pokazać mi swoją app.xaml? I wyjaśnij proszę, w jaki sposób główne okno wiąże się z głównym widokiem Mai UserControl. Dzięki! – shadox

+0

W jaki sposób UserControl dowiedział się o DataTemplate? A jeśli jest w niektórych ResourceDictionary, UserControl powinien o tym wiedzieć, prawda? –

+0

Możesz umieścić go w słowniku zasobów lub w window.resources lub app.resources, zależy to od twoich potrzeb. – user1064519

Powiązane problemy