As we know, there is not possible customize Markup Extension in Silverlight 4 because the IMarkupExtension interface has only internal access in this version.
Version 5 of Silverlight, extends ours horizons.
Below, I will show how we can achive our goal.
using System; using System.Windows; using System.Windows.Input; using System.Xaml; using Microsoft.Practices.Prism.Commands; namespace CommandingSL5 { public class Commanding : IMarkupExtension<ICommand> { public string MethodName { get; set; } public ICommand ProvideValue(IServiceProvider serviceProvider) { if (!String.IsNullOrEmpty(MethodName)) { if (serviceProvider == null) return null; var rootService = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider)); var root = rootService.RootObject as FrameworkElement; if (root != null) { if (root.DataContext != null) { var method = root.DataContext.GetType().GetMethod(MethodName); if (method != null) { return new DelegateCommand(() => method.Invoke(root.DataContext, null)); } } } } return null; } } }
Interface IServiceProvider gives us possibility to get specific service which allows us access to target element (where was used our custom Markup Extension) or root element which is our View with associated ViewModel by property DataContext.
IRootObjectProvider: provide a reference to the Root object of the VisualTree which the element is part of
IXamlTypeResolver : is able to resolve the name of the tags in the markup to the corresponding type.
IProvideValueTarget : gets a reference to the property and the elements which the markup extension is assigned
(Source: Andrea Boschin Blog)
As we see, there is no problem to using more complex methods because I use .NET Reflection which gives me many possibilities.
Usage:
<UserControl x:Class="CommandingSL5.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:c="clr-namespace:CommandingSL5" mc:Ignorable="d"> <UserControl.DataContext> <c:MainPageViewModel /> </UserControl.DataContext> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="150" /> </Grid.ColumnDefinitions> <TextBox Text="{Binding MethodAText}" Margin="5,5" /> <Button Content="Execute TestMethod A" Command="{c:Commanding MethodName=TestMethodA}" Margin="5,5" Grid.Column="1"/> </Grid> </UserControl>
and also our ViewModel:
using System.ComponentModel; namespace CommandingSL5 { public class MainPageViewModel : INotifyPropertyChanged { #region Fields private string _methodAText; #endregion #region Properties public string MethodAText { get { return _methodAText; } set { _methodAText = value; RaisePropertyChanged("MethodAText"); } } #endregion #region Methods public void TestMethodA() { MethodAText = "TestMethodA executed !"; } #endregion #region INotifyPropertyChanged Implementation public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } #endregion } }
Brak komentarzy:
Prześlij komentarz