locked
MarkupExtension only initialized once in DataTemplate in .Net 4 RRS feed

  • Question

  • Hi,

    I create a LocalizationProvider markup extension to support multi-language in my application. In .Net 3.5, everything works fine, but after i upgrade to .Net 4, sometimes the LocalizationProvider fails to work. After debug i found that the LocalizationProvider contained in a data template only be constructed once in .Net 4, but in .Net 3.5 it will be constructed many times (every time the data template is applied). And that's the problem, i need a individual LocalizationProvider for each item the template is applied.

    Same codes: (The LocaliztionItem (derived from frameworkelement) in the xaml also initialized once only. And I found a workaround: If  i change the LocalizationItem in xaml like this <localization:LocalizationItem Tag="{StaticResource brush}" ...  the LocalizationProvider will be constructed many times again. )

    <Window x:Class="LocalizationTestApp.MainWindow"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:localization="clr-namespace:KM.Client.Core.Common.Localization"
     xmlns:res="clr-namespace:LocalizationTestApp.Properties"
     Title="MainWindow" Height="350" Width="525">
     <Window.Resources>
     <SolidColorBrush x:Key="brush" Color="White"/>
     </Window.Resources>
     <DockPanel LastChildFill="False" >
     <ListBox ItemsSource="{Binding Items}" DockPanel.Dock="Top" HorizontalAlignment="Center">
     <ListBox.ItemTemplate>
      <DataTemplate>
       <TextBlock Margin="20,0">
        <TextBlock.Text>
        <localization:LocalizationProvider>
         <localization:LocalizationProvider.Item>
          <localization:LocalizationItem ItemResourceManager="{x:Static res:Resources.ResourceManager}" 
                  ResourceKey="{Binding ResourceKey}"/>
         </localization:LocalizationProvider.Item>
        </localization:LocalizationProvider> 
        </TextBlock.Text>
       </TextBlock>
      </DataTemplate>
     </ListBox.ItemTemplate>
     </ListBox>
    
     <Button Content="Change language" DockPanel.Dock="Bottom" Margin="20" Click="Button_Click" />
     </DockPanel>
    </Window>
    
     public class LocalizationProvider : MarkupExtension
     {
     public LocalizationProvider()
     {
      Item = new LocalizationItem();
     }
    
     public override object ProvideValue(IServiceProvider serviceProvider)
     {
      IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
      FrameworkElement trgUsercontrol = target.TargetObject as FrameworkElement;
      if (trgUsercontrol == null)
      {
       //The ProviderValue method will be called agained by return this.
       return this; 
      }
    
      Item.Target = trgUsercontrol;
      Item.Property = target.TargetProperty as DependencyProperty;
    
      SetBindings(trgUsercontrol.DataContext);
      trgUsercontrol.DataContextChanged += new DependencyPropertyChangedEventHandler(OnTargetElementDataContextChanged);
    
      if (!string.IsNullOrEmpty(Item.ResourceKey))
      {
       if (Item.ItemResourceManager != null)
       {
        Item.ResourceValue = Item.ItemResourceManager.GetObject(Item.ResourceKey); 
       }
       else
       {
        Item.ResourceValue = Item.ResourceKey;
       }
      }
      else
      {
        Item.ResourceValue = null;
      }
    
      return Item.ResourceValue;
     }
    
     .......
    }
    
     public class LocalizationItem : FrameworkElement
     {
     public void UpdateResource()
     {
      if (Target != null && Property != null && !string.IsNullOrEmpty(ResourceKey))
      {
       object resourceValue = null;
       if (ItemResourceManager == null)
       {
        resourceValue = ResourceKey;
       }
       else
       {
        resourceValue = ItemResourceManager.GetObject(ResourceKey);
       }
     
       Target.SetValue(Property, resourceValue);
      }
     }
    
     public static readonly DependencyProperty ItemResourceManagerProperty = DependencyProperty.Register(
       "ItemResourceManager", typeof(ResourceManager), typeof(LocalizationItem),
       new PropertyMetadata(new PropertyChangedCallback(OnResourceManagerChanged)));
    
     public static readonly DependencyProperty ResourceKeyProperty = DependencyProperty.Register(
      "ResourceKey", typeof(string), typeof(LocalizationItem),
      new PropertyMetadata(new PropertyChangedCallback(OnResourceKeyChanged)));
    
     public FrameworkElement Target
     {
      get
      {
       return m_Target;
      }
    
      internal set
      {
       m_Target = value;
       DataContext = m_Target.DataContext;
       m_Target.DataContextChanged += OnTargetDataContextChanged;
      }
     }
     ......
    }
    
    • Moved by SamAgain Friday, October 29, 2010 3:25 AM better fit (From:.NET Base Class Library)
    Thursday, October 28, 2010 3:09 AM

All replies

  • Hello,

    Could not get the code to compile. Looking over this, your reporting that a MarkupExtension is only being constructed once. Created a small MarkupExtension and it seems to be constructed for each instance of an item in the containing Listbox, so we haven’t been able to reproduce the issue you are reporting.

    Can you give another way to repro?


    bill boyce
    Friday, November 12, 2010 8:30 PM
  • Hi,

    Thank you. I have created a sample project and uploaded it to SkyDrive, maybe you can try that. http://cid-61dac77ca466d39b.office.live.com/self.aspx/%e5%85%ac%e5%85%b1/LocalizationTestApp.zip

    If the target framework version is set to .Net 4.0 only the last item in list box displayed, but if i downgrade the target framework to .Net 3.5, it works again.


    Bin
    Monday, November 15, 2010 1:59 AM
  • Hi, Is there anyone tried my sample and reproduced this problem? I don't know much about the MarkupExtenstion and i really need your help.
    Bin
    Friday, December 10, 2010 3:10 AM
  • Did you ever solve this i am having the same issue?
    Thursday, November 8, 2012 4:34 AM
  • No, this problem is still there.

    Bin

    Wednesday, November 14, 2012 1:46 AM