Note: Forums will be making significant UX changes to address key usability improvements surrounding search, discoverability and navigation. To learn more about these changes please visit the announcement which can be found HERE.
StaticResourceExtension : need to implément IXamlSchemaContextProvider in design time

Pertanyaan StaticResourceExtension : need to implément IXamlSchemaContextProvider in design time

  • 03 Maret 2011 13:52
     
      Memiliki Kode

    Hi all,

    I use a bindable static resource extension that inherit from StaticResourceExtension.

    It's work in run time, so very well.

    But in design time, I have the error : The markup extension 'BindableStaticResource' require that 'IXamlSchemaContextProvider' is implemented in the IServiceProvider of ProvideValue.  

    See the BindableStaticResourceExtension code:

    using System;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Markup;
    using System.Xaml;
    
    namespace WinningGames.Core
    {
    	/// <summary>
    	/// Define a bindable static resource
    	/// </summary>
    	public class BindableStaticResource : StaticResourceExtension
    	{
    		private bool dataContextChangeHandlerSet = false;
        /// <summary>
    		/// Create a bindable static resource
    		/// </summary>
    		public BindableStaticResource()
    			: base()
    		{
    			Binding = new Binding();
    		}
    
    		/// <summary>
    		/// Create a bindable static resource
    		/// </summary>
    		/// <param name="binding">Binding used to retrive the resource key</param>
    		public BindableStaticResource(Binding binding)
    			: base()
    		{
    			Binding = binding;
    		}
    
    		/// <summary>
    		/// Provide a value for the target property
    		/// </summary>
    		/// <param name="serviceProvider">Service provider for the markup extension</param>
    		/// <returns>Value for the target property</returns>
    		public override object ProvideValue(IServiceProvider serviceProvider)
    		{
          // Get the service
    			IProvideValueTarget provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
    			if(provideValueTarget != null)
    			{
    				// Get the target element
    				FrameworkElement targetElement = provideValueTarget.TargetObject as FrameworkElement;
            /* if (targetElement == null)
              targetElement = provideValueTarget.TargetObject as FrameworkElement;*/
    				if(targetElement != null)
    				{
    					// If the data context change handler has not been setted
    					if(!dataContextChangeHandlerSet)
    					{
    						// Add an handler
    						targetElement.DataContextChanged += new DependencyPropertyChangedEventHandler(targetElement_DataContextChanged);
    						dataContextChangeHandlerSet = true;
    					}
    
    					// If the binding has none source
    					if(String.IsNullOrEmpty(Binding.ElementName) && Binding.RelativeSource == null && Binding.Source == null)
    						// Use the datacontext of the target
    						Binding.Source = targetElement.DataContext;
    				}
    			}
    
    			// Create a dummy object to simulate the binding
    			DependencyObject dummyObject = new DependencyObject();
    			// Set the dummy binding
    			BindingOperations.SetBinding(dummyObject, DummyProperty, Binding);
    			// Get the binded value and use it as resource key
    			this.ResourceKey = dummyObject.GetValue(DummyProperty);
    			// Return the resource
    			return ResourceKey != null ? base.ProvideValue(serviceProvider) : null;
    		}
    
    		/// <summary>
    		/// Get or set the resource key
    		/// </summary>
    		public new object ResourceKey
    		{
    			get
    			{
    				return base.ResourceKey;
    			}
    			set
    			{
    				// We accept a null value without set it
    				if(value != null)
    					base.ResourceKey = value;
    			}
    		}
    
    		/// <summary>
    		/// Get or set the binding used to retrieve the resource key
    		/// </summary>
    		public Binding Binding { get; set; }
    
    		/// <summary>
    		/// Occurs when the datacontext of the target object has changed
    		/// </summary>
    		/// <param name="sender">Event sender</param>
    		/// <param name="e">Event argument</param>
    		private void targetElement_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    		{
          /*Binding = new Binding();
          Binding.Path = new PropertyPath("Name");
          ProvideValue(serviceProvider);*/
    			// TODO : Call the ProvideValue method
    		}
    
    		/// <summary>
    		/// Dummy property used to simulate the binding
    		/// </summary>
    		private static readonly DependencyProperty DummyProperty = DependencyProperty.Register("Dummy", typeof(object), typeof(DependencyObject));
    	}
    }
    

    and the use :

    <UserControl x:Class="WinningGames.PieceView"
      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"
      mc:Ignorable="d"
    	xmlns:core="clr-namespace:WinningGames.Core"
    	Height="45" Width="45" 
      DataContext="{Binding Piece, Source={StaticResource Locator}}"
      Grid.Column="{Binding X}" Grid.Row="{Binding Y}">
      <UserControl.Resources>
    		<ResourceDictionary Source="Resources/ResourceDictionary.xaml" />
      </UserControl.Resources>
      <UserControl.Content>
    		<core:BindableStaticResource Binding="{Binding Name}" />
      </UserControl.Content>
    </UserControl>
    

     

    Have you an idea to help me?

     

    Thanks