2012-12-31 31 views
5

Tôi đang cố gắng ràng buộc Chế độ xem với một ViewModel trong ResourceDictionary nhưng nó không hoạt động.Kết nối dữ liệu WPF với ResourceDictionary MVVM

Ứng dụng này rất đơn giản với 2 hộp văn bản. Khi tôi nhập văn bản vào textbox1, atutomatically, textbox2 phải nhận được cùng một văn bản. Tất nhiên các hộp văn bản của tôi từ View phải được liên kết với các thuộc tính của tôi trong ViewModel.

Tôi mới để WPF và cách tôi bắt đầu để ràng buộc xem và ViewModels là trong codebehind của một Xem:

DataContext = new MyViewModel(); 

Bây giờ tôi đang cố gắng để đạt được một sự tách biệt rõ ràng hơn. Mã của tôi là

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:

tôi đã thay đổi TestData tài sản như sau:

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

     } 
    } 

Và implemened các INotifyPropertyChanged như thế này:

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

Bạn có gặp phải bất kỳ lỗi nào trong cửa sổ Đầu ra không? – Thelonias

+0

Không có lỗi, không có cảnh báo. Nó chỉ không hoạt động. – shadox

+0

Tôi không nghĩ DataContext của bạn đang được đặt cho 'MainWindowView' của bạn. Tôi nghĩ, thay vào đó, 'MainWindowViewModel' là DataContext cho' MainResourceDictionary'. Bởi vì bạn đã thiết lập StartupURI của bạn thành MainWindowView, nó sẽ tạo ra một cá thể của Window của bạn, nhưng không bao giờ thiết lập DataContext. Tôi không tích cực, nhưng tôi không nghĩ rằng ResourceDictionary của bạn đang làm bất cứ điều gì vào thời điểm này. – Thelonias

Trả lời

4

nên user1064 519 đã đi đúng hướng:

  • View cần phải được một UserControl, không phải là một Window, vì nó được lưu trữ trong MainWindow
  • ViewModel cần được nạp vào MainWindow, đây là những gì trigger DataTemplate được phát hiện và tải.

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

Sau đó bạn nên lên và chạy. Tôi đã đăng một ví dụ chuyên sâu tại đây: wpf bootstrapping datatemplates--the chicken and the egg

+0

Tôi nghĩ TheZenker phản hồi rất tốt trên blog của mình được liên kết ở đây. – shadox

1

ViewModel của bạn phải thực hiện các giao diện INotifyPropertyChanged và nâng cao một sự kiện PropertyChanged khi bất kỳ giá trị thuộc tính ràng buộc nào thay đổi, để chế độ xem của bạn có thể biết rằng thay đổi được làm mờ.

+0

Nó vẫn không hoạt động ... một người bạn của tôi đề nghị chỉ định RelativeSource ... somthing về tổ tiên ... mà tôi thực sự không hiểu. – shadox

1

DataTemplate sholudnt chứa cửa sổ, nó có thể chứa bất kỳ loại điều khiển nào.

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

Thực ra nó không hoạt động ... bạn có thể chỉ cho tôi app.xaml của bạn được không? Và giải thích làm thế nào để cửa sổ chính liên kết với chế độ xem chính UserControl. Cảm ơn! – shadox

+0

Cách UserControl của bạn biết về DataTemplate? Và nếu nó là trong một số ResourceDictionary, UserControl nên biết về nó, phải không? –

+0

Bạn có thể đặt nó trong hoặc từ điển tài nguyên hoặc window.resources hoặc app.resources, nó phụ thuộc vào nhu cầu của bạn – user1064519

Các vấn đề liên quan