Click here to Skip to main content
12,398,816 members (61,278 online)
Click here to Skip to main content

Stats

15.9K views
306 downloads
22 bookmarked
Posted

MVVM for Multi Platforms

, 22 Mar 2010 CPOL
How to implement MVVM when developing a view model whose view implementation language is not certain
GeographicRepresentation
bin
Release
GeographicRepresentation.Interfaces.dll
GeographicRepresentation.Interfaces.pdb
GeographicRepresentation.Lib.dll
GeographicRepresentation.Lib.pdb
GeographicRepresentation.TestLib.dll
GeographicRepresentation.TestLib.pdb
GeographicRepresentation.UILib.exe
GeographicRepresentation.UILib.pdb
GeographicRepresentation.UILib.vshost.exe
GeographicRepresentation.UILib.vshost.exe.manifest
Resources
GeographicRepresentation.suo
GeographicRepresentation.TestLib
bin
Debug
GeographicRepresentation.Interfaces.dll
GeographicRepresentation.Lib.dll
GeographicRepresentation.TestLib.dll
Release
Properties
GeographicRepresentation.vsmdi
Interfaces
bin
Debug
GeographicRepresentation.Interfaces.dll
Release
Properties
Lib
bin
Debug
GeographicRepresentation.Interfaces.dll
GeographicRepresentation.Lib.dll
Release
Model
Properties
Resources
ViewModel
LocalTestRun.testrunconfig
TestResults
UILib
bin
Debug
GeographicRepresentation.UILib.exe
WpfApplication1.vshost.exe.manifest
Release
GeographicRepresentation.UILib.vshost.exe.manifest
Properties
UILib.csproj.user
View
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

using GeographicRepresentation.Interfaces;
using GeographicRepresentation.UILib.View;
using GeographicRepresentation.Lib;

namespace GeographicRepresentation.UILib
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class MainWindow : Window, IDisposable
    {
        #region delegates

        internal delegate void RemoveObjectFromViewDelegate(IReadOnlyViewModel vm);

        #endregion

        #region Members

        public static RoutedUICommand cmd_AddContinent = new RoutedUICommand("addContinent", "addContinent", typeof(MainWindow));
        public static RoutedUICommand cmd_AddCountry = new RoutedUICommand("addCountry", "addCountry", typeof(MainWindow));
        public static RoutedUICommand cmd_AddCity = new RoutedUICommand("addCity", "addCity", typeof(MainWindow));
        public static RoutedUICommand cmd_EditObject = new RoutedUICommand("editObject", "editObject", typeof(MainWindow));
        public static RoutedUICommand cmd_RemoveObject = new RoutedUICommand("removeObject", "removeObject", typeof(MainWindow));
        
        Timer m_Timer;

        #endregion

        #region Properties

        /// <summary>
        /// Show the current time
        /// </summary>
        public string CurrentTime
        {
            get
            {
                return DateTime.Now.ToLongTimeString();
            }
        }

        #endregion

        #region Methods

        #region Ctor

        public MainWindow()
        {
            InitializeComponent();

            CommandBinding cb = new CommandBinding(cmd_AddContinent, onAddContinent, canAddContinent);
            CommandBindings.Add(cb);
            cb = new CommandBinding(cmd_AddCountry, onAddCountry, canAddCountry);
            CommandBindings.Add(cb);
            cb = new CommandBinding(cmd_AddCity, onAddCity, canAddCity);
            CommandBindings.Add(cb);
            cb = new CommandBinding(cmd_EditObject, onEditObject, canEditObject);
            CommandBindings.Add(cb);
            cb = new CommandBinding(cmd_RemoveObject, onRemoveObject, canRemoveObject);
            CommandBindings.Add(cb);
            
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.DataContext = this;

            m_Timer = new Timer(this.GetCurrentTime);
            m_Timer.Change(1000, 1000);            
        }

        #endregion

        private void onAddContinent(object sender, ExecutedRoutedEventArgs args)
        {
            EditContinentWindow window = new EditContinentWindow();
            bool? b = window.ShowDialog();
            if ((b != null) && (b == true))
            {
                treeView.UpdateData();
            }
        }
        
        private void canAddContinent(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = true;
        }


        private void onAddCountry(object sender, ExecutedRoutedEventArgs args)
        {
            IReadOnlyContinentViewModel vm = treeView.SelectedObject as IReadOnlyContinentViewModel;
            EditCountryWindow window = new EditCountryWindow(true, vm.Id);
            bool? b = window.ShowDialog();
            if ((b != null) && (b == true))
            {
                treeView.UpdateData();
            }
        }

        /// <summary>
        /// Validate if a country could be added. Only possible when the cursor is on a continent
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void canAddCountry(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = treeView.SelectedObject != null &&
                              treeView.SelectedObject.GetType().GetInterfaces().Contains(typeof(IReadOnlyContinentViewModel));
        }

        private void onAddCity(object sender, ExecutedRoutedEventArgs args)
        {
            IReadonlyCountryViewModel vm = treeView.SelectedObject as IReadonlyCountryViewModel;
            EditCityWindow window = new EditCityWindow(true, vm.Id);
            bool? b = window.ShowDialog();
            if ((b != null) && (b == true))
            {
                treeView.UpdateData();
            }
        }

        /// <summary>
        /// Validate if a city could be added. Only possible when the cursor is on a country
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void canAddCity(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = treeView.SelectedObject != null &&
                              treeView.SelectedObject.GetType().GetInterfaces().Contains(typeof(IReadonlyCountryViewModel));
        }

        /// <summary>
        /// Upon removing object, get the current object and asynchronsou
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void onRemoveObject(object sender, ExecutedRoutedEventArgs args)
        {
            this.Cursor = Cursors.Wait;
            IContinentsListViewModel vm = treeView.DataContext as IContinentsListViewModel;
            RemoveObjectFromViewDelegate delg = new RemoveObjectFromViewDelegate(vm.RemoveGeographicObject);
            delg.BeginInvoke(treeView.SelectedObject, new AsyncCallback(this.OperationCompleted), delg);
        }   

        private void OperationCompleted(IAsyncResult result)
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new AsyncCallback(this.OperationCompletedInMainThread), result);
        }

        private void OperationCompletedInMainThread(IAsyncResult result)
        {
            this.Cursor = Cursors.Arrow;

            RemoveObjectFromViewDelegate delg = result.AsyncState as RemoveObjectFromViewDelegate;
            delg.EndInvoke(result);
            treeView.UpdateData();
        }

        private void canRemoveObject(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = treeView.SelectedObject != null;
        }

        private void onEditObject(object sender, ExecutedRoutedEventArgs args)
        {
            Window window = null;
            if (treeView.SelectedObject.GetType().GetInterfaces().Contains(typeof(IReadOnlyContinentViewModel)))
            {
                window = new EditContinentWindow(((IReadOnlyContinentViewModel)treeView.SelectedObject).Id);
            }
            else if (treeView.SelectedObject.GetType().GetInterfaces().Contains(typeof(IReadonlyCountryViewModel)))
            {
                window = new EditCountryWindow(false,((IReadonlyCountryViewModel)treeView.SelectedObject).Id);
            }
            else if (treeView.SelectedObject.GetType().GetInterfaces().Contains(typeof(IReadOnlyCityViewModel)))
            {
                window = new EditCityWindow(false,((IReadOnlyCityViewModel)treeView.SelectedObject).Id);
            }
            
            bool? b = window.ShowDialog();
            if ((b != null) && (b == true))
            {
                treeView.UpdateData();
            }
        }

        private void canEditObject(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = treeView.SelectedObject != null;
        }

        /// <summary>
        /// Example for data refresh
        /// </summary>
        private void GetCurrentTime(object state)
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new SimpleOperationDelegate(this.CurrentTimeUpdated));
        }

        private void CurrentTimeUpdated()
        {
            BindingExpression bindingExpression =
                BindingOperations.GetBindingExpression(txtCurrentTime, TextBlock.TextProperty);
            bindingExpression.UpdateTarget();
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (m_Timer != null)
            {
                m_Timer.Dispose();
            }
        }

        #endregion        

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Izhar Lotem
Software Developer
Israel Israel
Software Developer in a promising Clean-Tech company

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160721.1 | Last Updated 22 Mar 2010
Article Copyright 2010 by Izhar Lotem
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid