2011-03-02 35 views

回答

16

您需要在轉換器資源指定x:Shared="False"。這裏是一個例子:

<BooleanToVisibilityConverter x:Key="MyConverter" x:Shared="False"/> 
+0

帕夫洛取代普通轉換器你是男人! – NVM 2011-03-02 11:31:57

2

您可以在每個控制單獨的資源:

<TextBox> 
     <TextBox.Resources> 
      <Converters:VisibilityConverter x:Key="conv"/> 
     </TextBox.Resources> 
     <TextBox.Text> 
      <Binding Converter="{StaticResource conv}"/> 
     </TextBox.Text> 
    </TextBox> 
1

爲什麼?它應該是確定性的,並且不知道除了通過參數傳遞給它的任何狀態。我已經使用了值轉換器來保存圖像的靜態列表(將值轉換爲圖像),並且工作正常 - 即使在具有數千行的數據網格的多個列中使用相同的轉換器時也是如此。 (請注意,轉換器仍不知道任何外部狀態)。

在任何情況下,看是否能回答你的問題:Are value converters instantiated per-binding in WPF?

+2

我需要一個轉換器來綁定兩個可觀察的集合或稍微不同的類型。我跟蹤轉換器中收集已更改的事件。因此每個實例。 – NVM 2011-03-02 11:31:27

0

如果你把你的轉換器轉化爲資源,並通過{StaticResource ConverterName}查找引用它們,那麼他們每個實例化資源字典的情況只有一次。

但是更好的方法是從MarkupExtension繼承您的轉換器,並直接使用它們,而不是將它們添加到資源並引用它們。

下面是這樣一個基類的一個實例:

http://www.snippetsource.net/Snippet/18/base-class-for-valueconverters-in-wpf

問候 基督教

+0

鏈接已死,請更新,如果它仍然存在 – Maslow 2017-02-16 13:36:22

0

MarkupExtension繼承,然後創建在構造函數中的轉換器。

public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     _converter = new FlagsToBoolConverter(); 
     return _converter; 
    } 

下面是一個完整的例子。它是一個需要實例化的標誌轉換器,以保留ConvertBack的源值。

using System; 
using System.Globalization; 
using System.Runtime.CompilerServices; 
using System.Windows; 
using System.Windows.Data; 
using System.Windows.Markup; 

namespace Something 
{ 
    public class FlagsToBoolConverter : MarkupExtension, IValueConverter 
    { 
     private FlagsToBoolConverter _converter; 

     public override object ProvideValue(IServiceProvider serviceProvider) 
     { 
      _converter = new FlagsToBoolConverter(); 
      return _converter; 
     } 

     private ulong _sourceValue; 

     public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      try 
      { 
       var type = value.GetType(); 
       if (type.IsEnum) 
       { 
        ulong mask = (ulong)System.Convert.ChangeType(Enum.Parse(type, (string)parameter), typeof(ulong)); 
        _sourceValue = (ulong)System.Convert.ChangeType(Enum.Parse(type, value.ToString()), typeof(ulong)); 
        return ((mask & _sourceValue) != 0); 
       } 
       return value; 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("FlagsEnumValueConverter: Invalid Cast(to) Value={0} Type={1} Param={2} Exception{3}", value, targetType, parameter, ex); 
      } 
      return value; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      try 
      { 
       if (targetType.IsEnum) 
       { 
        var original = this._sourceValue; 
        var originalEnum = Enum.Parse(targetType, original.ToString()); 
        var maskEnum = Enum.Parse(targetType, (string)parameter); 
        var mask = (ulong)System.Convert.ChangeType(maskEnum, typeof(ulong)); 
        _sourceValue ^= mask; 
        var sourceEnum = Enum.Parse(targetType, _sourceValue.ToString()); 
        Console.WriteLine($"Modified Value: {original} ({originalEnum}) by Mask {mask} ({maskEnum}) Result = {_sourceValue} ({sourceEnum})"); 
        return sourceEnum; 
       } 
       return value; 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("FlagsEnumValueConverter: Invalid Cast(from) Value={0} Type={1} Param={2} Exception{3}", value, targetType, parameter, ex); 
      } 
      return value; 
     } 
    } 
} 

您的前綴需要聲明爲xmlns:src="clr-namespace:Something"。然後在你的綁定與Converter={src:FlagsToBoolConverter}

<CheckBox IsChecked="{Binding SomeFlagsEnum, ConverterParameter=FlagA, Converter={src:FlagsToBoolConverter}}">FlagA</CheckBox> 
    <CheckBox IsChecked="{Binding SomeFlagsEnum, ConverterParameter=FlagB, Converter={src:FlagsToBoolConverter}}">FlagB</CheckBox> 
    <CheckBox IsChecked="{Binding SomeFlagsEnum, ConverterParameter=FlagC, Converter={src:FlagsToBoolConverter}}">FlagC</CheckBox>