Binding data items on second window
Finally I decided to jump on the WPF bandwagon and decided to follow the MVVM Pattern to create my applications. I am also using Caliburn.Micro.
I found many examples of Binding data to Windows but all the examples contained just one MainWindow. I couldn't figure out how to reference and make the binding when opening a second and third window. To illustrate my problem I created a simple application. This application has two windows, the main one named ShellView and the second one named Window1View. All I need in this application is to display the content of myStr1 into the TextBox on Window1View.
Here is the code:
Views.ShellView.xaml
<Window x:Class="Test.Views.ShellView"
xmlns="ht开发者_StackOverflow社区tp://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock x:Name="Title" />
<Button Content="Window 1" Height="31" HorizontalAlignment="Left" Margin="24,268,0,0" Name="btnWin1" VerticalAlignment="Top" Width="87" Click="btnWin1_click" />
</Grid>
</Window>
Views.ShellView.xaml.cs
namespace Test.Views
{
using System.Windows;
public partial class ShellView : Window
{
public ShellView()
{
InitializeComponent();
}
private void btnWin1_click(object sender, RoutedEventArgs e)
{
Window1View win1 = new Window1View();
win1.Show();
}
}
}
ViewModels.ShellViewModel.cs
namespace Test.ViewModels
{
using Caliburn.Micro;
public class ShellViewModel : PropertyChangedBase
{
public static string txt1 = "String 1";
public static string txt2 = "String 2";
private string title;
public string Title
{
get { return title; }
set
{
if (title != value)
{
title = value;
RaisePropertyChangedEventImmediately("Title");
}
}
}
public ShellViewModel()
{
Title = "Hello Caliburn.Micro";
}
}
}
Views.Window1View.xaml
<Window x:Class="Test.Views.Window1View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
Title="Window 1" Height="300" Width="300">
<Grid>
<Label Content="TextBox 1" Height="26" HorizontalAlignment="Left" Margin="12,40,0,0" Name="label1" VerticalAlignment="Top" Width="75" />
<TextBox Height="29" HorizontalAlignment="Left" Margin="106,39,0,0" Name="txtBox1" VerticalAlignment="Top" Width="145" Text="{Binding myStr1}" />
</Grid>
</Window>
View.Window1View.xaml.cs
using System.Windows;
namespace Test.Views
{
/// <summary>
/// Interaction logic for Window1View.xaml
/// </summary>
public partial class Window1View : Window
{
public Window1View()
{
InitializeComponent();
}
}
}
ViewModels.Window1ViewModel.cs
namespace Test.ViewModels
{
class Window1ViewModel
{
public Window1ViewModel()
{
myStr1 = ShellViewModel.txt1;
}
public string myStr1 { get; set; }
}
}
Bootstrapper.cs
namespace Test
{
public class Bootstrapper : Caliburn.Micro.Bootstrapper<Test.ViewModels.ShellViewModel>
{
}
}
App.xaml
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Test.App">
<Application.Resources>
</Application.Resources>
</Application>
App.xaml.cs
namespace Test
{
using System.Windows;
public partial class App : Application
{
Bootstrapper bootstrapper;
public App()
{
bootstrapper = new Bootstrapper();
}
}
}
Any help with this would be greatly appreciated.
Thanks CarmeloMaybe I'm missing something because I'm not familiar with Caliburn.Micro, but I see a couple of things going on here.
First, I don't see anywhere that you're setting the DataContext
of the Window1View
to be an instance of Window1ViewModel
.
Second, your Window1ViewModel
doesn't derive from PropertyChangedBase
and you don't call RaisePropertyChanged
when you change the myStr1 property.
A common way to implement view model communication in MVVM is to use the Mediator Pattern. Most MVVM frameworks include a 'Messenger' class that allows you to decouple your design by publishing and subscribing to events. In Caliburn Micro, mediation is supported by the EventAggregator class.
Since you are new to MVVM, I would also recommend the following resources:
- Implementing the MVVM Pattern
- Advanced MVVM Scenarios
- User Interaction Patterns
A few things here:
- You are using code behind unnecessarily. Ideally you should aim for virtually no code behind when using MVVM. Instead of creating a
btnWin1_click
handler, name the button and implement a method on your view model with the same name. Caliburn.Micro will invoke the view model method based on convention. - Use x:Name rather than Name
- When displaying the
Window1ViewModel
, you are not using Caliburn.Micro to invoke the window display. This means that no binding exists between yourWindow1View
andWindow1ViewModel
. If this is a separate window, use theWindowManager
type from Caliburn.Micro. Instantiate yourWindow1ViewModel
, and use theWindowManager
class to display it. Caliburn.Micro will locate the appropriate view based on conventions, and bind the view to your view model. - As mentioned, rather than reference the
ShellViewModel
directly in theWindow1ViewModel
(which couples the view models and makesWindow1ViewModel
less reuseable), use the mediator pattern. Caliburn.Micro comes with an EventAggregator class - you can publish the change in text from theShellViewModel
, and subscribe to the event in yourWindow1ViewModel
.
精彩评论