Векторное изображение в шаблоне кнопки WPF не всегда отображается - PullRequest
0 голосов
/ 28 октября 2018

У меня есть приложение WPF с парой кнопок, на которых нет текста, только векторное изображение (с использованием объекта Path), шаблон ControlTemplate выглядит следующим образом:

<ControlTemplate x:Key="IconButtonContentTemplate" TargetType="{x:Type ButtonBase}">
    <Grid Background="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}">
        <Path HorizontalAlignment="Center" VerticalAlignment="Center" 
            Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}" 
            Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}"   
            Data="{Binding (components:ImageButtonAttachedProperties.ImagePathData), RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}"
            Stretch="Uniform" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, Mode=FindAncestor}}" />
    </Grid>

    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Foreground" Value="LightGray" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Foreground" Value="LightGray" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="Gray" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate> 


<Style TargetType="{x:Type Button}" x:Key="ClockButtonStyle" BasedOn="{StaticResource IconButtonStyle}">
    <Setter Property="Template" Value="{StaticResource IconButtonContentTemplate}" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="components:ImageButtonAttachedProperties.ImagePathData" Value="M69.349,65.092C68.714,65.092,68.072,64.925,67.487,64.577L46.294,51.946 46.294,21.239C46.294,19.227 47.925,17.595 49.938,17.595 51.949,17.595 53.581,19.227 53.581,21.239L53.581,47.807 71.217,58.317C72.945,59.348 73.512,61.585 72.483,63.312 71.799,64.457 70.589,65.092 69.349,65.092z M49.938,3.877C24.573,3.877 3.938,24.513 3.938,49.877 3.938,75.241 24.573,95.877 49.938,95.877 75.302,95.877 95.938,75.241 95.938,49.877 95.938,24.513 75.302,3.877 49.938,3.877z M52.876,88.467C52.882,88.395 52.897,88.324 52.897,88.25 52.897,86.615 51.572,85.29 49.937,85.29 48.302,85.29 46.977,86.615 46.977,88.25 46.977,88.324 46.994,88.395 46.999,88.467 27.994,87.032 12.783,71.822 11.349,52.817 11.423,52.822 11.492,52.838 11.567,52.838 13.202,52.838 14.527,51.513 14.527,49.878 14.527,48.243 13.201,46.918 11.567,46.918 11.492,46.918 11.422,46.935 11.349,46.94 12.783,27.933 27.994,12.722 47,11.287 46.995,11.36 46.978,11.43 46.978,11.504 46.978,13.139 48.304,14.464 49.938,14.464 51.572,14.464 52.897,13.138 52.897,11.504 52.897,11.429 52.881,11.36 52.876,11.287 71.882,12.722 87.093,27.932 88.528,46.938 88.455,46.933 88.385,46.916 88.311,46.916 86.676,46.916 85.35,48.242 85.35,49.876 85.35,51.51 86.676,52.836 88.311,52.836 88.385,52.836 88.455,52.82 88.528,52.815 87.094,71.822 71.883,87.032 52.876,88.467z" />
</Style>

Моя проблема в том, чтов очень редких случаях изображение кнопки не отображается (в 99% случаев).На кнопку все еще можно нажать, но изображение на ней не отображается.Я не уверен, что вызывает это.Связывание данных на векторном изображении?Или привязка данных к цвету заливки?

ImageButtonAttachedProperties.ImagePathData - это System.Windows.Media.Geometry объект, который описывает векторное изображение.

public static class ImageButtonAttachedProperties
{
    public static readonly DependencyProperty ImagePathDataProperty =
        DependencyProperty.RegisterAttached("ImagePathData", typeof(Geometry), typeof(ImageButtonAttachedProperties), new UIPropertyMetadata(null));

    public static Geometry GetImagePathData(DependencyObject obj)
    {
        return (Geometry)obj.GetValue(ImagePathDataProperty);
    }

    public static void SetImagePathData(DependencyObject obj, Geometry value)
    {
        obj.SetValue(ImagePathDataProperty, value);
    }
}

Есть идеи, что я здесь не так делаю?

Ответы [ 3 ]

0 голосов
/ 01 ноября 2018

Вы должны:

1) Удалите привязку данных на цвете заливки, чтобы определить, можете ли вы по-прежнему воспроизвести проблему.

Если вы не можете, попробуйте сделать это наоборот:

2) Удалите привязку данных на пути (используйте постоянный путь для тестирования) и выполните тестирование с привязкой данных на цвете заливки.

Если 1) и 2) не может воспроизвести вашу проблему, топопробуйте: 3) Используйте постоянные значения для цвета заливки и привязку данных на пути

Если вы смогли воспроизвести проблему в 1) или 2), теперь вы знаете, по крайней мере, источник проблемы.То же самое верно для 3), но это более сложно, потому что 3) подразумевает, что обе привязки данных как-то влияют друг на друга ...

4) Также возможно, что ваша проблема более глубоко погружена в определение ваших тем - так что переключениеОтключение пользовательских тем и использование только тем Generics - это также способ проверки, чтобы узнать источник проблемы.

5) Я также попытался бы разметить Path на фоне кнопки, чтобы увидеть, если этоведет себя лучше по отношению к вашей проблеме - см. мой последний комментарий в этом посте: Изображение заполнить пространство на кнопке в WPF

Вам действительно нужно опубликовать небольшое демонстрационное приложение, чтобы получить детерминированныйответьте, в противном случае, я боюсь, что невозможно сказать точный источник, учитывая только показанные фрагменты

0 голосов
/ 06 ноября 2018

Вы связываете требуемые размеры элемента шаблона с окончательными размерами шаблонного родителя;это создает круговую зависимость.Не делайте этого.

Размер шаблонного элемента управления (например, вашего Button) зависит от желаемого размера содержимого его шаблона (например, вашего Path).Если вы сделаете размер содержимого зависимым от размера шаблонного родителя, вы просто напрашиваетесь на неприятности.

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

Избавьтесь от привязок Width и Height на ваших Path и установите горизонтальное и вертикальное выравнивание на Stretch.

0 голосов
/ 31 октября 2018

Я не уверен, что является причиной этого.

В какой-то момент значения ActualWidth или ActualHeight (для любого элемента управления) фактически равны нулю, и эти свойствасвойства зависимости типа только для чтения.Это происходит, когда элементом управления является Loaded, Measured, Arranged или Rendered.

Согласно FrameworkElement.ActualWidth Свойство

Поскольку ActualWidth является вычисленным значением, вы должны знать, что в него могут быть внесены множественные или инкрементные изменения в результате различных операций системы макетов.Система компоновки может вычислять требуемое пространство мер для дочерних элементов, ограничений родительского элемента и т. Д.

Вопрос в том, что что-то покачивает вашу кнопку и вызываетизмените размер, и вы выиграете в лотерею , поймав нулевое значение.


В качестве примера того, что можно попробовать, я дал ответ о размещении векторного изображения Лучший способиспользовать векторное изображение в WPF двумя различными способами, и в примере, который я использовал, было 3 вектора в окне с изменяемым размером, и, насколько мне известно, они не flash, за исключением перерисовки.Но я установил высоту / ширину stretch.

Может быть, изменить способ удержания вектора?

...