Overblog Suivre ce blog
Administration Créer mon blog

Présentation

  • : Romagny13 - Du .NET,du pur .NET
  • Romagny13 - Du .NET,du pur .NET
  • : Cycle de progression Faire (quelque chose qui marche) -> comprendre ce que l’on fait/comment cela marche -> pousser plus loin les notions
  • Contact

Recherche

Articles Récents

12 avril 2014 6 12 /04 /avril /2014 20:31

Soit une enum quelconque .Le but étant d’afficher la valeur de la description dans les contrôles de l’UI

public enum Status 
    {
        [Description("Mon état A")]
        StateA,
        [Description("Mon état B")]
        StateB
    }
On utilise un converter
       public class EnumDescriptionConverter : IValueConverter 
    {
        public object Convert(object value,Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null) return null;
            string description = GetDescription(value);
            return description;
        }
        public object ConvertBack(object value,Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }
        private static string GetDescription(object value)
        {
            FieldInfo field = value.GetType().GetField(value.ToString());
            DescriptionAttribute attribute = field.GetCustomAttribute(typeof(DescriptionAttribute), false) as DescriptionAttribute;
            string description = (attribute != null) ? attribute.Description : field.Name;
            return description;
        }
      }
Utilisation
J’ai un viewModel simple  et le DataContext de ma page réglé dessus.
  public class OrderViewModel :ViewModelBase 
    {
      private Status _orderStatus;
        public Status OrderStatus
        {
            get { return _oederStatus; }
            set 
            {
                _orderStatus = value;
                RaisePropertyChanged<Status>(() => OrderStatus);
            }
        }
    }
Pour afficher dans un contrôle de texte
    <Grid.Resources> 
            <converter:EnumDescriptionConverter x:Key="enumDescriptionConverter" />           
    </Grid.Resources>
<TextBlock Text="{Binding OrderStatus,Converter={StaticResource enumDescriptionConverter}}"/> 
Pour afficher dans une liste + sélection
<Grid.Resources> 
            <converter:EnumDescriptionConverter x:Key="enumDescriptionConverter" /> 
           
            <ObjectDataProvider x:Key="statusEnum" MethodName="GetValues" ObjectType="{x:Type sys:Enum}"> 
                <ObjectDataProvider.MethodParameters> 
                    <x:Type Type="{x:Type local:Status}" /> 
                </ObjectDataProvider.MethodParameters> 
            </ObjectDataProvider>
           
            <DataTemplate x:Key="ItemTemplateCurrent">
                <TextBlock
                       Text="{Binding .,Converter={StaticResource enumDescriptionConverter}}" />
            </DataTemplate>
        </Grid.Resources>
        <ListBox ItemsSource="{Binding Source={StaticResource statusEnum}}"
                  SelectedValue="{Binding OrderStatus}"
                  ItemTemplate="{StaticResource ItemTemplateCurrent}" />
Repost 0
Published by Romagny13 - dans MVVM
commenter cet article
2 avril 2014 3 02 /04 /avril /2014 17:50

 

 
MainWindow

 

   <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.50*" />
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Column="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="30"/>
                <RowDefinition/>
            </Grid.RowDefinitions>
 
            <Button Command="{Binding DisplayArticleListViewCommand}" Content="Liste d'articles" Grid.Row="0" Margin="5 5 5 5" />
            <Button Command="{Binding DisplayArticleViewCommand}" Content="Détails"  Grid.Row="1" Margin="5 5 5 5"/>
        </Grid>
 
           <ContentPresenter Content="{Binding CurrentViewModel}"  Grid.Column="1"/>
    </Grid>

 
MainWiewModel

  public class MainViewModel : ViewModelBase
    {
        // ViewModels affichables
        public ArticleListViewModel ArticleListViewModel { get; set; }
        public ArticleViewModel ArticleViewModel { get; set; }
        private ViewModelBase _currentViewModel;
        // ViewModel courant
        public ViewModelBase CurrentViewModel
        {
            get { return _currentViewModel; }
            set
            {
                _currentViewModel = value;
                RaisePropertyChanged<ViewModelBase>(() => CurrentViewModel);
            }
        }
        // Commandes
        public RelayCommand<MainViewModel> DisplayArticleListViewCommand { get; set; }
        public RelayCommand<MainViewModel> DisplayArticleViewCommand { get; set; }
 
        public MainViewModel() { }
        protected override void InitializeCommands()
        {
            DisplayArticleListViewCommand = new RelayCommand<MainViewModel>(_ => DisplayArticleListView(), this);
            DisplayArticleViewCommand = new RelayCommand<MainViewModel>(_ => DisplayArticleView(), this);
        }
 
        private void DisplayArticleListView()
        {
            if (ArticleListViewModel == null)
                ArticleListViewModel = new ArticleListViewModel();
 
            CurrentViewModel = ArticleListViewModel;
        }
 
        private void DisplayArticleView()
        {
            if (ArticleViewModel == null)
                ArticleViewModel = new ArticleViewModel();
 
            CurrentViewModel = ArticleViewModel;
        }    
    }

 

En ressource (permet de définir la View associée à un ViewModel) 
        <DataTemplate DataType="{x:Type ViewModel:ArticleListViewModel}">
            <View:ArticleListView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type ViewModel:ArticleViewModel}">
            <View:ArticleView />
        </DataTemplate>

 

Le code des ViewModels et Views est classique et présente peu d’intérêt .
A savoir que l’on définit le DataContext de MainWidow sur nouveau MainViewModel
Plus loin
Il est possible aussi de définir une ObservableCollection<ViewModelBase> ou créer une classe spécifique qui hérite de ViewModelBase et utiliser un control comme le TabControl
Repost 0
Published by Romagny13 - dans MVVM
commenter cet article
29 mars 2014 6 29 /03 /mars /2014 17:53

J’utilise la réflexion.

L’avantage est de ne pas avoir à implémenter IEditableObject dans chaque POCO  .Il y a peut-être moyen de faire mieux mais l’idée est là.
Exemple avec ModelBase avec MVVM .
    public class ModelBase :
        ObservedBase,
        IDataErrorInfo,
        IEditableObject
    {
 
       // code retiré pour la clarté
 
       #region IEditableObject
 
        private Dictionary<string, object> _cache;
 
        public void BeginEdit()
        {
            _cache = new Dictionary<string, object>();
 
            IEnumerable<PropertyInfo> properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CanRead && p.CanWrite);
            foreach (PropertyInfo property in properties)                    
                _cache.Add(property.Name, property.GetValue(this, null));
                                 
 
        }
 
        public void CancelEdit()
        {
            if (_cache != null)
            {
                IEnumerable<PropertyInfo> properties = this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.CanRead && p.CanWrite);
 
                foreach (PropertyInfo property in properties)
                    property.SetValue(this, _cache[property.Name], null);
 
                _cache = null;
            }
        }
 
        public void EndEdit()
        {
            _cache = null;                    
        }
 
        #endregion
    } 

 

 
Repost 0
Published by Romagny13 - dans MVVM
commenter cet article
10 mars 2014 1 10 /03 /mars /2014 12:58

RelayCommand

public class RelayCommand : ICommand
    {
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;
 
        public RelayCommand(Action<object> execute): this(execute, null){ }
        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null) throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute;
        }
 
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }
        public event EventHandler CanExecuteChanged
        {
            add {CommandManager.RequerySuggested += value;}
            remove {CommandManager.RequerySuggested -= value;}
        }
        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }

 

Le bouton :
<Button Content="Supprimer" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RemoveImageCommand}" CommandParameter="{Binding .}" />

 

  • Il faut spécifier la source de données car sinon cela va chercher la commande … dans l’observableCollection .Exemple si je mettais simplement  Command="{Binding RemoveImageCommand}"  cela irait chercher la commande à exécuter dans la collection de photos et non le ViewModel
  • CommandParameter : c’est l’objet à passer, ici j’envoie la photo courante ( {Binding .} et {Binding} c'est la même chose)

La listBox d’un userControl le bouton et l’ItemTemplate(simplifié pour la clarté de l'exemple) 

 

<ListBox  ItemsSource="{Binding Article.Photos}" >
                                <ListBox.ItemTemplate>
                                    <DataTemplate>
                                        <WrapPanel>
                                            <Image Source="{Binding Picture}" />
                                            <Button Content="Supprimer" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RemoveImageCommand}" CommandParameter="{Binding .}" />
                                        </WrapPanel>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                            </ListBox>

 

Dans le ViewModel (ArticleViewModel dans mon exemple)

 

        public RelayCommand RemoveImageCommand { get; private set; }
 
        protected override void InitializeCommands()
        {
            RemoveImageCommand = new RelayCommand(RemoveImage);           
        }
 
        public void RemoveImage(object image)
        {
            if (Article != null && image !=null)
            {
                if (dialogService.Confirm("Suppression d'image", "Voulez-vous supprimer l'image ? "))
                {
                    Article.Photos.Remove((PhotoModel)image); 
                }
            }
        }
 

 

Repost 0
Published by Romagny13 - dans MVVM
commenter cet article
4 mars 2014 2 04 /03 /mars /2014 20:40
  • Permet de « centraliser l’ensemble des services de l’application » (les services du Model)
  • Un peu comme le ViewModelLocator qui lui s’occupe du ViewModel
Enregistrement des services :
App.xaml.cs
  protected override void OnStartup(StartupEventArgs e)
        {
 
            base.OnStartup(e);
 
            RegisterServices();
            RegisterViewModels();
 
        }
        private void RegisterServices()
        {
            ServiceLocator.Instance.Register<IMessenger>(new Messenger());
            ServiceLocator.Instance.Register<IArticleService>(new ArticleService());
            ServiceLocator.Instance.Register<ICollectionService>(new CollectionService());
            ServiceLocator.Instance.Register<IColorService>(new ColorService());
            ServiceLocator.Instance.Register<IPhotoService>(new PhotoService());
            ServiceLocator.Instance.Register<ISizeService>(new SizeService());
            ServiceLocator.Instance.Register<IGenderService>(new GenderService());
            ServiceLocator.Instance.Register<ICategoryService>(new CategoryService());
        }
        private void RegisterViewModels()
        {
            ViewModelLocator.Register(new ArticleListViewModel());
            ViewModelLocator.Register(new ArticleViewModel());
            ViewModelLocator.Register(new FilterViewModel());
            // . . .
        }

 

Retrouver un service depuis un ViewModel
       private IMessenger messenger;
       private IArticleService articleService;
 
        // . . .
        protected override void InitializeServices()
        {
            messenger = ServiceLocator.Instance.Retrieve<IMessenger>();
            articleService = ServiceLocator.Instance.Retrieve<IArticleService>();
        }

Utiliser un service .Il est possible ensuite d’utiliser ce même service .

public class ServiceLocator
    {     
        // Singleton
        private static readonly ServiceLocator instance = new ServiceLocator();
 
        public static ServiceLocator Instance
        {
            get { return instance; }
        }
 
        private Dictionary<Type, object> container = new Dictionary<Type, object>();
 
        public void Register<T>(T element)
        {
            container.Add(typeof(T), element);
        }
 
        public T Retrieve<T>()
        {
            object item;
            if (container.TryGetValue(typeof(T), out item))
                return (T)item;
 
            return default(T);
        }
 
        public void Unregister<T>()
        {
            if (container.ContainsKey(typeof(T)))
            {
                container.Remove(typeof(T));
            }
        }
    }

 

Repost 0
Published by Romagny13 - dans MVVM
commenter cet article
2 mars 2014 7 02 /03 /mars /2014 20:03

1 ViewModelLocator "simple"

Exemple

  public class ViewModelLocator
    {
        public MainViewModel MainViewModel { get; set; }   
        public ArticleListViewModel ArticleListViewModel { get; set; }
        public ArticleDetailsViewModel ArticleDetailsViewModel { get; set; }
 
        public ViewModelLocator()
        {
            MainViewModel = new MainViewModel();
            ArticleListViewModel = new  ArticleListViewModel();
            ArticleDetailsViewModel = new ArticleDetailsViewModel();
        }
    }

Puis dans App.xaml

<Application x:Class="MVVMExample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:ViewModels="clr-namespace:MVVMExample.ViewModels"
             xmlns:Framework="clr-namespace:MVVMExample.Framework"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
 
            <!-- etc. -->
            <Framework:ViewModelLocator x:Key="viewModelLocator"/>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Utilisation

 <Views:ArticleListView DataContext="{Binding ArticleListViewModel, Source={StaticResource viewModelLocator}}" />

 

2-Un ViewModelLocator générique
« Framework » (dossier ou projet)
public class ViewModelLocator
    {
        private readonly static Dictionary<string, ViewModelBase>cache = new Dictionary<string, ViewModelBase>();
 
        public ViewModelBase this[string key]
        {
            get
            {
                ViewModelBase viewModel;
                cache.TryGetValue(key, out viewModel);
                return viewModel;
            }
        }
        public static void Register(string key, ViewModelBase viewModel)
        {
            cache.Add(key, viewModel);
        }
        public static void Register(ViewModelBase viewModel)
        {
            Register(viewModel.GetType().Name, viewModel);
        }      
        public static void Register<TViewModel>(ViewModelBase viewModel)
        {
            Register(typeof(TViewModel).Name, viewModel);
        }      
    }

 

App.xaml.cs
On enregistre les ViewModel
public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
 
            RegisterViewModels();
        }
        private void RegisterViewModels()
        {
            ViewModelLocator.Register(new MainViewModel());
            ViewModelLocator.Register(new ArticleListViewModel());
            ViewModelLocator.Register(new ArticleDetailsViewModel());
        }
    }

 

App.xaml
<Framework:ViewModelLocator x:Key="viewModelLocator"/>

 

Utilisation
<Views:ArticleListView DataContext="{Binding .[ArticleListViewModel], Source={StaticResource viewModelLocator}}" />

 

Repost 0
Published by Romagny13 - dans MVVM
commenter cet article