2012-02-10 4 views
1

Я, кажется, столкнулся с некоторым поведением в отношении WPF ResourceDictionaries, Brushes и Styles (по крайней мере, это то, что я заметил до сих пор), что противоречит моему пониманию того, как эти вещи должны работать. В принципе, если я ссылаюсь на кисть из сеттера с стилем в ResourceDictionary, он заставляет кисть замораживаться. Пример ниже иллюстрирует это, так как я получаю InvalidOperationException, когда я пытаюсь изменить цвет в общей кисти в обработчике события Click моей кнопки. Это должно привести к изменению цвета Rectangle, поскольку оба они используют один и тот же общий Brush, но вместо этого я получаю исключение.Style Setter Freezing Brush

<Window x:Class="MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <SolidColorBrush x:Key="TestBrush" Color="Red" /> 
     <Style TargetType="Rectangle"> 
      <Setter Property="Fill" Value="{StaticResource TestBrush}" /> 
     </Style> 
    </Window.Resources> 
    <StackPanel> 
     <Button Name="Button1" Content="Change Color" Click="Button1_Click" /> 
     <Rectangle Height="20" /> 
     <Rectangle Height="20" /> 
    </StackPanel> 
</Window> 
public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Button1_Click(object sender, RoutedEventArgs e) 
    { 
     var brush = (SolidColorBrush)FindResource("TestBrush"); 
     // InvalidOperationException Here. Brush is Frozen/Read-Only 
     brush.Color = Colors.Blue; 
    } 
} 

Если я просто удалить стиль (более конкретно сеттер) и ссылки на кисти (до сих пор от ResourceDictionary) непосредственно из каждого прямоугольника, я получаю ожидаемое поведение цветов прямоугольников меняется в тандеме из события нажатия кнопки. См. Код ниже (кнопка click event hanlder остается той же).

<Window x:Class="MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <SolidColorBrush x:Key="TestBrush" Color="Red" /> 
    </Window.Resources> 
    <StackPanel> 
     <Button Name="Button1" Content="Change Color" Click="Button1_Click" /> 
     <Rectangle Height="20" Fill="{StaticResource TestBrush}" /> 
     <Rectangle Height="20" Fill="{StaticResource TestBrush}" /> 
    </StackPanel> 
</Window> 

Я только вижу кисть становится замороженной, когда он упоминается как StaticResource из сеттер стиля, в. Я могу actaully ссылаться на тот же Brush из других мест в ResourceDictionary, не замораживая; т.е. содержимое ControlTemplates.

Может кто-нибудь объяснить, что происходит с этим странным поведением, и если это по дизайну или ошибка?

Спасибо, Brandon

ответ

1

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

См http://msdn.microsoft.com/en-us/library/ms745683.aspx

+0

Спасибо Дмитрию, но я не пытаюсь изменить стиль. Мой вопрос относится к тому, что кисть становится замороженной (IsFrozen = true) просто наличием сеттера в стиле, который ссылается на него как на StaticResource. Обратите внимание, что (хотя я упоминаю об этом, но не включил пример), я могу использовать кисть в других местах в стиле, не замораживая ее, пока она не находится в Setter (то есть внутри самой ControlTemplate). – Brandon

+0

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