2015-04-01 3 views
4

Это не MahApps.Metro-specific, но это то, что я использую. У меня есть набор ViewModels, у которого есть свойство string, представляющее, какой значок использовать из ресурсного файла XAML.Как использовать переменную ViewModel для DynamicResource?

public class CommandViewModel : ViewModel 
{ 
    public CommandViewModel(string displayName, ICommand command, string icon) 
    { 
     if (command == null) 
      throw new ArgumentNullException("command"); 

     DisplayName = displayName; 
     Command = command; 
     Icon = icon; 
    } 

    public ICommand Command { get; private set; } 
    public string Icon { get; set; } 
} 

Icon будет в конечном итоге что-то вроде "appbar_add" от MahApps.Metro.Resources. Они определены в файле Icons.xaml.

Как написать это в моем ItemTemplate так, чтобы отображался правильный ресурс. Я либо получаю ошибки при выполнении (не при редактировании/сборке), либо вообще не получаю никаких значков.

«ничто не значок» XAML выглядит следующим образом:

<ItemsControl ItemsSource="{Binding}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal"> 
       <Rectangle Width="20" Height="20"> 
        <Rectangle.Fill> 
         <VisualBrush Visual="{DynamicResource {Binding Path=Icon}}" /> 
        </Rectangle.Fill> 
       </Rectangle> 
       <TextBlock Margin="15,6">        
        <Hyperlink Command="{Binding Path=Command}"> 
         <TextBlock Text="{Binding Path=DisplayName}" /> 
        </Hyperlink> 
       </TextBlock> 
      </StackPanel> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Мои попытки, вызвавших ошибки использовали StaticResource, который я считаю в корне неправильным.

Как я могу ссылаться на свойство Icon как на имя ресурса, который я хочу?

Редактировать

Больше кода было предложено, так вот пример того, что делает работы:

<Rectangle Width="20" Height="20"> 
    <Rectangle.Fill> 
     <VisualBrush Visual="{StaticResource appbar_add}" /> 
    </Rectangle.Fill> 
</Rectangle> 

Что мне нужно сделать, это позволить «appbar_add» быть значение из свойства на моем ViewModel - Icon собственности выше.

ресурсы находятся в ResourceDictionary в отдельном файле (Icon.xaml) и выглядеть следующим образом:

<Canvas x:Key="appbar_add" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0"> 
    <Path Width="38" Height="38" Canvas.Left="19" Canvas.Top="19" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 35,19L 41,19L 41,35L 57,35L 57,41L 41,41L 41,57L 35,57L 35,41L 19,41L 19,35L 35,35L 35,19 Z "/> 
</Canvas> 
+0

Полезная ссылка: http://stackoverflow.com/questions/20564862/binding-to-resource-key-wpf – dugas

ответ

2

Вы можете использовать конвертер, чтобы сделать работу. см. приведенный ниже код. У меня есть два стиля, чтобы символ + был красного цвета или черного цвета в Icon.xaml.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<Canvas x:Key="appbar_add_Black" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0"> 
    <Path Width="38" Height="38" Canvas.Left="19" Canvas.Top="19" Stretch="Fill" Fill="Black" Data="F1 M 35,19L 41,19L 41,35L 57,35L 57,41L 41,41L 41,57L 35,57L 35,41L 19,41L 19,35L 35,35L 35,19 Z "/> 
</Canvas> 
<Canvas x:Key="appbar_add_Red" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0"> 
    <Path Width="38" Height="38" Canvas.Left="19" Canvas.Top="19" Stretch="Fill" Fill="Red" Data="F1 M 35,19L 41,19L 41,35L 57,35L 57,41L 41,41L 41,57L 35,57L 35,41L 19,41L 19,35L 35,35L 35,19 Z "/> 
</Canvas> 

Направить Просмотр кода. ViewModel

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      this.DataContext = new CommandViewModel("Red"); 
     } 
    } 

public class CommandViewModel :INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private void OnPropertyChanged(string propName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
    public CommandViewModel(string icon) 
    { 
     Icon = icon; 
    } 

    private string icon; 

    public string Icon 
    { 
     get { return icon; } 
     set { icon = value; } 
    } 

} 

class IconConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     string str = (string)value; 
     ResourceDictionary myResourceDictionary = new ResourceDictionary(); 
     myResourceDictionary.Source = 
       new Uri("Icon.xaml", 
         UriKind.Relative); 
     if (str.Equals("Black")) 
     {    
      return myResourceDictionary["appbar_add_Black"]; 
     } 
     else 
     { 
      return myResourceDictionary["appbar_add_Red"]; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

Это дает ошибку, потому что Icon - это строка (а не изображение), или потому что мне нужно ссылаться на ресурс по-разному для этого случая. Конвертер 'TargetDefaultValueConverter' не смог преобразовать значение '<Значения значка>'. 'И' IOException: 'System.IO.IOException: Не удается найти ресурс' <Значение значка> ''. Это значение отлично работает, когда оно используется непосредственно в коде, который я изначально разместил, в качестве VisualBrush Visual (''). При необходимости я могу предоставить более подробную информацию. –

+0

Вы пытаетесь дать полный путь к изображению? –

+0

Нет, просто имя, которое находится в файле Icons.xaml. «appbar_add», в этом случае. Прекрасно работает как StaticResource, но не работает как источник изображения. Должен ли я пытаться использовать более сложную ссылку на путь? –

2

Как говорит Ганеша, вы можете использовать конвертер. Я бы просто изменить конвертер немного от одного предложил:

public class FindResourceFromString: IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      if (value != null) return Application.Current.FindResource((string) value); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

Это берет строку в и возвращает ресурс (из словаря ресурсов). Вероятно, вы захотите, чтобы конвертер вернул значок заполнителя, если ресурс с именем строки не найден.

Часть XAML будет выглядеть примерно так:

<ItemsControl ItemsSource="{Binding}"> 
<ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <StackPanel Orientation="Horizontal"> 
      <Rectangle Width="20" Height="20"> 
       <Rectangle.Fill> 
        <VisualBrush Visual="{Binding Icon, Converter={StaticResource FindResourceFromStringConverter}}" /> 
       </Rectangle.Fill> 
      </Rectangle> 
      <TextBlock Margin="15,6">        
       <Hyperlink Command="{Binding Path=Command}"> 
        <TextBlock Text="{Binding Path=DisplayName}" /> 
       </Hyperlink> 
      </TextBlock> 
     </StackPanel> 
    </DataTemplate> 
</ItemsControl.ItemTemplate> 

Вы должны зарегистрировать конвертер в разделе ресурсов пользовательского элемента управления или окна, что ItemsControl находится в:

<UserControl.Resources> 
     <vc:FindResourceFromString x:Key="FindResourceFromStringConverter" /> 
</UserControl.Resources> 

Предполагается, что у вас есть конвертеры, доступные из пространства имен, называемого vc.

Смежные вопросы