Click here to Skip to main content
13,143,374 members (34,781 online)
Click here to Skip to main content

Stats

18K views
22 bookmarked
Posted 22 Mar 2010

MVVM for Multi Platforms

, 22 Mar 2010
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.Shapes;

using GeographicRepresentation.Lib;
using GeographicRepresentation.Interfaces;
using System.Threading;

namespace GeographicRepresentation.UILib.View
{
    /// <summary>
    /// Interaction logic for EditCityWindow.xaml
    /// </summary>
    public partial class EditCityWindow : Window, IDisposable    
    {
        #region Members

        Guid m_Id;
        bool m_bNew;
        IEditableCityViewModel m_DataContext;
        Timer m_Timer;
        DateTime m_CurrentTime;           

        public static RoutedUICommand cmd_SaveCity = new RoutedUICommand("saveCity", "saveCity", typeof(EditCityWindow));
        public static RoutedUICommand cmd_Cancel = new RoutedUICommand("cancelCity", "cancelCity", typeof(EditCityWindow));

        #endregion

        #region Methods

        #region Ctor
        
        /// <summary>
        /// Default Ctor
        /// </summary>
        /// <param name="bNew">a flag which determines if the purpose of the window is to create a new city or to edit an
        ///                    existing one</param>
        /// <param name="id">the id - country if new, city if edit</param>
        public EditCityWindow(bool bNew, Guid id)
        {
            m_bNew = bNew;
            m_Id = id;
            InitializeComponent();
            m_Timer = new Timer(this.GetCityTime);
        }
        

        #endregion

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            SimpleOperationDelegate delg = new SimpleOperationDelegate(this.GetDataContext);
            delg.BeginInvoke(new AsyncCallback(this.DataContextLoaded), delg);

            if (m_bNew)
            {
                this.Title = "Add city";
            }

            CommandBinding cb = new CommandBinding(cmd_SaveCity, onSave, canSave);
            CommandBindings.Add(cb);
            cb = new CommandBinding(cmd_Cancel, onCancel, canCancel);
            CommandBindings.Add(cb);
        }        

        /// <summary>
        /// A request for the data context
        /// </summary>
        private void GetDataContext()
        {
            if (m_bNew)
            {
                m_DataContext = InterfacesFactory.Instance.GetEditableCityViewModelForAdd(m_Id);
            }
            else
            {
                m_DataContext = InterfacesFactory.Instance.GetEditableCityViewModelForEdit(m_Id);
            }
        }

        /// <summary>
        /// The data context call back. Make all the adjustments in the main thread, using the dispatcher
        /// </summary>
        /// <param name="result"></param>
        private void DataContextLoaded(IAsyncResult result)
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new AsyncCallback(this.DataContextLoadedInMainThread), result);
        }

        /// <summary>
        /// Update the view
        /// </summary>
        /// <param name="result"></param>
        private void DataContextLoadedInMainThread(IAsyncResult result)
        {
            if (result.IsCompleted)
            {
                this.DataContext = m_DataContext;
                SimpleOperationDelegate delg = result.AsyncState as SimpleOperationDelegate;
                delg.EndInvoke(result);                
                Button saveButton = (Button)this.Template.FindName("saveButton", this);
                if (saveButton != null)
                {
                    saveButton.Command = EditCityWindow.cmd_SaveCity;
                }
                Button cancelButton = (Button)this.Template.FindName("cancelButton", this);
                if (cancelButton != null)
                {
                    cancelButton.Command = EditCityWindow.cmd_Cancel;
                }
                if (!m_bNew)
                {                    
                    this.Title = string.Format("Edit {0}", m_DataContext.CityName);
                    m_Timer.Change(1000, 1000);
                }                
            }
        }

        /// <summary>
        /// Use the view model to request data
        /// </summary>
        /// <param name="state"></param>
        private void GetCityTime(object state)
        {
            m_CurrentTime = m_DataContext.GetCurrentTime();
            // update the data from the main window
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new SimpleOperationDelegate(this.UpdateCurrentTime));
        }

        private void UpdateCurrentTime()
        {
            this.Title = string.Format("Edit {0}. Current time at city {1}", m_DataContext.CityName, m_CurrentTime.ToLongTimeString());
        }

        private void onSave(object sender, ExecutedRoutedEventArgs args)
        {
            this.Cursor = Cursors.Wait;
            SimpleOperationDelegate delg = new SimpleOperationDelegate(this.SaveOperation);
            delg.BeginInvoke(this.OperationCompleted, delg);
        }

        /// <summary>
        /// Textual data validation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void canSave(object sender, CanExecuteRoutedEventArgs args)
        {
            int n;
            args.CanExecute = txtName.Text.Length > 0 &&
                              int.TryParse(txtPopulation.Text, out n) &&                              
                              n > 0;
        }       

        private void SaveOperation()
        {
            m_DataContext.Save();
        }

        /// <summary>
        /// The operation call back. Call the dispatcher to update the view from the main thread
        /// </summary>
        /// <param name="result"></param>
        private void OperationCompleted(IAsyncResult result)
        {
            System.Windows.Application.Current.Dispatcher.BeginInvoke(new AsyncCallback(this.EndOperation), result);
        }

        /// <summary>
        /// End the asynchronos call
        /// </summary>
        /// <param name="result"></param>
        private void EndOperation(IAsyncResult result)
        {
            this.Cursor = Cursors.Arrow;

            SimpleOperationDelegate delg = result.AsyncState as SimpleOperationDelegate;
            delg.EndInvoke(result);
            this.DialogResult = true;
            this.Close();   
        }

        /// <summary>
        /// The cancelation button should run if this is the edit mode, othewise, simply close the window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void onCancel(object sender, ExecutedRoutedEventArgs args)
        {
            if (!m_bNew)
            {
                this.Cursor = Cursors.Wait;
                SimpleOperationDelegate delg = new SimpleOperationDelegate(this.CancelOperation);
                delg.BeginInvoke(this.OperationCompleted, delg);
            }
            else
            {
                this.Close();
            }
        }


        private void canCancel(object sender, CanExecuteRoutedEventArgs args)
        {
            args.CanExecute = true;
        }

        private void CancelOperation()
        {
            m_DataContext.Cancel();
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (m_Timer != null)
            {
                m_Timer.Change(Timeout.Infinite, Timeout.Infinite);
                m_Timer.Dispose();
            }
        }

        #endregion        

        #endregion

        
    }

    /// <summary>
    /// Create a collection for the data to present it in the XAML as an object data provider
    /// </summary>
    public class UTCTimePresenterCollection
    {
        public IList<short> GetValues()
        {
            List<short> list = new List<short>();
            for (short iter = -12; iter < 12; iter++)
            {
                list.Add(iter);
            }
            return list;
        }
    }
}

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

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