Dot-Net

WPF ImageSource 與自定義轉換器綁定

  • January 18, 2018

我有一個以這種方式構造的組合框的簡單模板:

<ComboBox DockPanel.Dock="Left" MinWidth="100" MaxHeight="24"
         ItemsSource="{Binding Actions}">
   <ComboBox.ItemTemplate>
       <DataTemplate>
           <StackPanel Orientation="Horizontal">
               <TextBlock Text="{Binding Name}" Width="100" />
               <Image Source="{Binding Converter={StaticResource TypeConverter}}" />
           </StackPanel>
       </DataTemplate>
   </ComboBox.ItemTemplate>
</ComboBox>

所以,如果我使用這段程式碼,一切正常:

<TextBlock Text="{Binding Name}" Width="100" />
<!--<Image Source="{Binding Converter={StaticResource TypeConverter}}" /> -->
<Image Source="{StaticResource SecurityImage}" />

但是,如果我使用轉換器,它就不再起作用了。這是轉換器,但我不知道如何從那裡引用靜態資源……

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
   var type = (Action)value;
   var img = new BitmapImage();
   switch (type.ActionType)
   {
       case ActionType.Security:
           img.UriSource = new Uri("StructureImage", UriKind.Relative);
           break;
       case ActionType.Structural:
           img.UriSource = new Uri("SecurityImage", UriKind.Relative);
           break;
   }

   return img;
}

嘗試使用 Josh 編寫的 Switch Converter,應該對您有用:

開關轉換器 –

XAML 的“開關語句” - http://josheinstein.com/blog/index.php/2010/06/switchconverter-a-switch-statement-for-xaml/

無需編寫轉換器,您的程式碼將如下所示 -

<Grid.Resources>  
   <e:SwitchConverter x:Key="ActionIcons">  
       <e:SwitchCase When="Security" Then="SecurithImage.png" />  
       <e:SwitchCase When="Structural" Then="StructureImage.png" />             
   </e:SwitchConverter>  
</Grid.Resources>  

<Image Source="{Binding Converter={StaticResource ActionIcons}}" />  

更新1:

這是 SwitchConverter 的程式碼,因為Josh 的網站似乎已關閉 -

/// <summary>
/// A converter that accepts <see cref="SwitchConverterCase"/>s and converts them to the 
/// Then property of the case.
/// </summary>
[ContentProperty("Cases")]
public class SwitchConverter : IValueConverter
{
   // Converter instances.
   List<SwitchConverterCase> _cases;

   #region Public Properties.
   /// <summary>
   /// Gets or sets an array of <see cref="SwitchConverterCase"/>s that this converter can use to produde values from.
   /// </summary>
   public List<SwitchConverterCase> Cases { get { return _cases; } set { _cases = value; } }
   #endregion
   #region Construction.
   /// <summary>
   /// Initializes a new instance of the <see cref="SwitchConverter"/> class.
   /// </summary>
   public SwitchConverter()
   {
       // Create the cases array.
       _cases = new List<SwitchConverterCase>();
   }
   #endregion

   /// <summary>
   /// Converts a value.
   /// </summary>
   /// <param name="value">The value produced by the binding source.</param>
   /// <param name="targetType">The type of the binding target property.</param>
   /// <param name="parameter">The converter parameter to use.</param>
   /// <param name="culture">The culture to use in the converter.</param>
   /// <returns>
   /// A converted value. If the method returns null, the valid null value is used.
   /// </returns>
   public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
       // This will be the results of the operation.
       object results = null;

       // I'm only willing to convert SwitchConverterCases in this converter and no nulls!
       if (value == null) throw new ArgumentNullException("value");

       // I need to find out if the case that matches this value actually exists in this converters cases collection.
       if (_cases != null && _cases.Count > 0)
           for (int i = 0; i < _cases.Count; i++)
           {
               // Get a reference to this case.
               SwitchConverterCase targetCase = _cases[i];

               // Check to see if the value is the cases When parameter.
               if (value == targetCase || value.ToString().ToUpper() == targetCase.When.ToString().ToUpper())
               {
                   // We've got what we want, the results can now be set to the Then property
                   // of the case we're on.
                   results = targetCase.Then;

                   // All done, get out of the loop.
                   break;
               }
           }

       // return the results.
       return results;
   }

   /// <summary>
   /// Converts a value.
   /// </summary>
   /// <param name="value">The value that is produced by the binding target.</param>
   /// <param name="targetType">The type to convert to.</param>
   /// <param name="parameter">The converter parameter to use.</param>
   /// <param name="culture">The culture to use in the converter.</param>
   /// <returns>
   /// A converted value. If the method returns null, the valid null value is used.
   /// </returns>
   public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
       throw new NotImplementedException();
   }
}

/// <summary>
/// Represents a case for a switch converter.
/// </summary>
[ContentProperty("Then")]
public class SwitchConverterCase
{
   // case instances.
   string _when;
   object _then;

   #region Public Properties.
   /// <summary>
   /// Gets or sets the condition of the case.
   /// </summary>
   public string When { get { return _when; } set { _when = value; } }
   /// <summary>
   /// Gets or sets the results of this case when run through a <see cref="SwitchConverter"/>
   /// </summary>
   public object Then { get { return _then; } set { _then = value; } }
   #endregion
   #region Construction.
   /// <summary>
   /// Switches the converter.
   /// </summary>
   public SwitchConverterCase()
   {
   }
   /// <summary>
   /// Initializes a new instance of the <see cref="SwitchConverterCase"/> class.
   /// </summary>
   /// <param name="when">The condition of the case.</param>
   /// <param name="then">The results of this case when run through a <see cref="SwitchConverter"/>.</param>
   public SwitchConverterCase(string when, object then)
   {
       // Hook up the instances.
       this._then = then;
       this._when = when;
   }
   #endregion

   /// <summary>
   /// Returns a <see cref="System.String"/> that represents this instance.
   /// </summary>
   /// <returns>
   /// A <see cref="System.String"/> that represents this instance.
   /// </returns>
   public override string ToString()
   {
       return string.Format("When={0}; Then={1}", When.ToString(), Then.ToString());
   }
}

更新2:

Microsoft 參考源中的另一個 SwitchConverter實現。

引用自:https://stackoverflow.com/questions/3204883