Источник изображения XAML устанавливается динамически в зависимости от содержимого - PullRequest
4 голосов
/ 29 июня 2010

Ну, на самом деле это не очень динамично, по крайней мере, не изменится во время выполнения.

Идея в том, что у меня есть кнопки, и у каждой есть уникальное изображение (значок 32x32). Все кнопки имеют общий стиль, в котором я использую шаблон ControlTemplate. Таким образом, каждое изображение также имеет 2 цвета: один нормальный, а другой - при наведении указателя мыши.

Я заметил, что когда я объявляю исходный путь к изображениям, они почти все одинаковы, поэтому я СУХОЙ (не повторяю себя). Что, если бы я мог использовать кнопку «Имя» или какое-либо другое свойство как часть исходного пути (то есть имя файла изображения). Это было бы хорошее программирование.

Проблема в том, что я новичок в XAML, WPF и, возможно, программирую все вместе, поэтому я не уверен, как это сделать. Я предполагаю, что для этого понадобится код или какой-то конвертер (наверное, я прочитаю о конвертерах чуть больше). Вот немного кода (это не работает, но дает общее представление (надеюсь)):

<Style x:Key="ButtonPanelBigButton" TargetType="{x:Type Button}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Border Name="ButtonBorder"
                        Height="78"
                        MaxWidth="70"
                        MinWidth="50"
                        BorderThickness="0.5"
                        BorderBrush="Transparent"
                        CornerRadius="8" >
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="2*" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>

                        <!-- Here I wan't to put in the Name property of the button because there is a picture there to match -->
                        <Image x:Name="ButtonIcon" Source="..\Images\Icons\32x32\Blue\{Binding Name}.png" 

                               Margin="4"
                               Height="32"
                               Width="32"
                               HorizontalAlignment="Center" 
                               VerticalAlignment="Center" />

                        <TextBlock Grid.Row="1"
                                   Padding="5,2,5,2"
                                   TextWrapping="Wrap"
                                   Style="{StaticResource MenuText}"
                                   HorizontalAlignment="Center"
                                   VerticalAlignment="Center">
                            <ContentPresenter ContentSource="Content" />                
                        </TextBlock>
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True" >
                        <Setter TargetName="ButtonIcon" Property="Source" Value="..\Images\Icons\32x32\Green\user.png" /> <!-- Same Here -->
                        <Setter TargetName="ButtonBorder" Property="BorderBrush" Value="{StaticResource SecondColorBrush}" />
                        <Setter TargetName="ButtonBorder" Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" Opacity="0.5">
                                    <GradientStop Color="{StaticResource MainColor}" Offset="1" />
                                    <GradientStop Color="{StaticResource SecondColor}" Offset="0.5" />
                                    <GradientStop Color="{StaticResource MainColor}" Offset="0" />
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Надеюсь, вы понимаете, куда я иду с этим, и кто-то может помочь мне, поэтому мой код хорош и СУХО (теперь я повторяюсь !!!).

1 Ответ

2 голосов
/ 30 июня 2010

Вы правы: самый простой способ решить эту проблему - использовать конвертер.

Свойство Source принимает ImageSource, поэтому вам нужно загрузить растровое изображение в конвертер самостоятельно.

Преобразователь используется следующим образом:

 <Image Source="{Binding Name,
                         RelativeSource={RelativeSource TemplatedParent},
                         Converter={x:Static local:ImageSourceLoader.Instance},
                         ConverterParameter=..\Images\Icons\32x32\Blue\{0}.png}" />

И реализован следующим образом:

public class ImageSourceLoader : IValueConverter
{
  public static ImageSourceLoader Instance = new ImageSourceLoader();

  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    var path = string.Format((string)parameter, value.ToString());
    return BitmapFrame.Create(new Uri(path, UriKind.RelativeOrAbsolute));
  }

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

Обратите внимание, что это простое решение не может обрабатывать относительный Uris, поскольку свойство BaseUri объектаИзображение недоступно для конвертера.Если вы хотите использовать относительный Uris, вы можете сделать это, связав присоединенное свойство и используя StringFormat:

 <Image local:ImageHelper.SourcePath="{Binding Name,
                         RelativeSource={RelativeSource TemplatedParent},
                         StringFormat=..\Images\Icons\32x32\Blue\{0}.png}" />

И PropertyChangedCallback присоединенного свойства обрабатывает изображение после объединения BaseUri с отформатированной строкой Uri:

public class ImageHelper : DependencyObject
{
  public static string GetSourcePath(DependencyObject obj) { return (string)obj.GetValue(SourcePathProperty); }
  public static void SetSourcePath(DependencyObject obj, string value) { obj.SetValue(SourcePathProperty, value); }
  public static readonly DependencyProperty SourcePathProperty = DependencyProperty.RegisterAttached("SourcePath", typeof(string), typeof(ImageHelper), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
      {
        ((Image)obj).Source =
          BitmapFrame.Create(new Uri(((IUriContext)obj).BaseUri, (string)e.NewValue));
      }
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...