New Posts New Posts RSS Feed: Beginners Question: how to port my YearCalendar Control to Cocktail?
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Beginners Question: how to port my YearCalendar Control to Cocktail?

 Post Reply Post Reply
Author
stipps View Drop Down
Newbie
Newbie


Joined: 01-Jun-2012
Posts: 1
Post Options Post Options   Quote stipps Quote  Post ReplyReply Direct Link To This Post Topic: Beginners Question: how to port my YearCalendar Control to Cocktail?
    Posted: 03-Jun-2012 at 3:44am
Hi,

I am a Hobby programmer and recently started to get to know the mvvm pattern with calibre.micro when i stumbled upon Cocktail.

I have a small wpf calendar application that we use in my Office to organize our Holidays, Business travels etc. To Display all the Events I created a custom yearcalendar user control, which simply calculates the days of the year, public Holidays etc. and build the Interface from the code behind file of the usercontrol.

I now try to rebuild the whole thing with Cocktail.
In General this worked nicely until now - i have a shellviewmodel that inherits from Conductor<YearCalendarViewModel>, and the YearCalendarViewModel calls the refresh method on my yearcalendar trough the IViewAware Interface.

The first time the calendar builds up nicely, no Problem. But when i try to Change the year displayed, and therefore habe to dispose all the generated controls and recreate them, the view does simply not react at all. It goes through the method that creates the calendar, but the UI does not update, it stays on the previous year. I as well tried to deactivate the YearCalendarViewModel on my ShellViewModel and add it again, but with no visible result.

Could anyone give me a hint how to resolve this, or how I should construct such a control so it works well with mvvm and Cocktail in particular?

Any help will be appreciated. I hope my english and the description of my Problem is understandable.

Regards,

Fredrik
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post Posted: 03-Jun-2012 at 5:09pm
The guiding rule of MVVM is that the ViewModel doesn't know the View. That's not always possible, so that's why Caliburn.Micro has OnViewLoaded through which you can get a reference to the view. This should only be used if the proper ways fail for reasons out of your control. The ViewModel doesn't need a reference to the view in general. The VM and V communicate which each other through the binding machinery. If you have your own custom control it should have custom DependencyProperties and Events that you can bind to data properties and actions in your ViewModel. You use a custom control just like a regular control. Since I don't know your custom control let me demonstrate this on a small example. In the following View we have a text box and a button. The TextBox Text DependencyProperty is two-way bound to the ViewModel and for the Button we bind the Click event to the ClearText action in the ViewModel.
<Window x:Class="SimpleMVVM.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.caliburnproject.org"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <TextBox Text="{Binding Text, Mode=TwoWay}" Width="200" Height="25" />
            <Button Content="Clear" cal:Message.Attach="[Event Click] = [Action ClearText]" Width="100"/>
        </StackPanel>
    </Grid>
</Window>
 
The corresponding ViewModel looks like this.
 
namespace SimpleMVVM
{
    [Export]
    class MainViewModel : Screen
    {
        private string _text;
 
        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                NotifyOfPropertyChange(() => Text);
            }
        }
 
        public void ClearText()
        {
            Text = "";
        }
    }
}
 
So, whenever the Text property changes in the ViewModel, the ViewModel triggers a PropertyChanged event, which tells the TextBox to refresh. That's why we can simple assign an empty string in the ClearText action to clear the TextBox.  Also, because we have defined the binding of Text as a Two-Way binding, if you type and tab out of the TextBox, the current value is automatically assigned to the Text property in our ViewModel. This is fundamentaly how View and ViewModels communicate. The two interfaces that make this all work are INotifyPropertyChanged and INotifyCollectionChanged for collections. Screen and Conductor in Caliburn.Micro implement INotifyPropertyChanged, so you can just call the NotifyOfPropertyChange method to trigger the event. BindableCollection which extends ObservableCollection implement INotifyCollectionChanged, which will refresh the View if for example you have a list box bound to a collection in your view model and you add or remove an item from the collection.
 
Now, Caliburn.Micro defines conventions that let you write less XAML. There are no conventions out of the box for your custom control, but you could write them yourself. For the standard controls like TextBox and Button, there are conventions, so the above XAML can be simplifed.
 
<Window x:Class="SimpleMVVM.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.caliburnproject.org"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <TextBox x:Name="Text" Width="200" Height="25" />
            <Button x:Name="ClearText" Content="Clear" Width="100"/>
        </StackPanel>
    </Grid>
</Window>

Now, Caliburn.Micro will perform the binding automatically. The TextBox is named the same as the property in the ViewModel, so Caliburn.Micro automatically establishes a two-way binding, since our property has a setter. Same for the button. The button's default event, which is Click, is automatically bound to the ClearText action method.

Having said all this, in MVVM you rarely create custom controls. Instead you leverage view composition. You can see that demonstrated in TempHire. TempHire is built using a number of smaller Views and ViewModels, which at runtime are composed together to the final application.

 
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down