воскресенье, 20 марта 2011 г.

StaticResource или DynamycResource

Огромное количество форумов по WPF наскидку вспоминаются этот и этот говорят о ровно следующее. Привязка через StaticResource берет объект ровно один раз из коллекции ресурсов. DynamicResource берет объект из коллекции ресурсов каждый раз когда он потребуется. Кроме того можно подменить объект на который ссылаемся на новый и привязка DynamicResource поймет, что объект изменился и ресурс будет затребован по-новой. Вроде бы ничего сложного. Очевидно, что StaticResource требует меньше затрат, чем DynamicResoure, поэтому без особой надобности DynamicResource использовать не стоит. Наглядно демонстрирует различие между StaticResource и DynamiResource простой пример. Сделаем простую разметку с code-behind. Вот разметка
 <Window x:Class="StaticAndDynamicResources.MainWindow"  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
           MouseLeftButtonUp="Window_MouseLeftButtonUp"  
           >  
      <Window.Resources>  
           <ResourceDictionary>  
                <SolidColorBrush Color="Yellow" x:Key="FGColor"/>  
           </ResourceDictionary>  
      </Window.Resources>  
   <Grid>  
           <Grid.ColumnDefinitions>  
                <ColumnDefinition Width="*"/>  
                <ColumnDefinition Width="*"/>  
           </Grid.ColumnDefinitions>  
           <GroupBox Header="StaticResource">  
                <Canvas Background="{StaticResource FGColor}"/>  
           </GroupBox>  
           <GroupBox Grid.Column="1" Header="DynamicResource">  
                <Canvas Background="{DynamicResource FGColor}"/>  
           </GroupBox>  
      </Grid>  
 </Window>  
вот code-behind
 public partial class MainWindow  
 {  
      public MainWindow()  
      {  
           InitializeComponent();  
      }  
      private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)  
      {  
           Resources[@"FGColor"] = new SolidColorBrush(Colors.Green);  
      }  
 }  
По клику мышки подменяется цвет кисти с желтого на зеленый. На интерфейсе все выглядит примерно так 3 Несложные исходники можно найти здесь. Теперь коснемся одной особенности StaticResource. Дело в том, что StaticResource вовсе не статичный, его можно изменять. Главное помнить,что StaticResource привязывается к одному объекту и его подменить не получится, но вот изменения в состоянии самого объекта будут влиять на значение поля к корому привязываем объект. На примере проще. Создадим класс SomeResource вот такой
 class SomeResource : INotifyPropertyChanged  
 {  
      int _nClicks = 0;  
      public int NClicks  
      {  
           get  
           {  
                return _nClicks;  
           }  
           protected set  
           {  
                _nClicks = value;  
                OnPropertyChanged("NClicks");  
           }  
      }  
      public ICommand IncCommand { get; protected set; }  
      public SomeResource()  
      {  
           IncCommand = new DelegateCommand(() => NClicks++);  
      }  
      #region INotifyPropertyChanged Members  
      public event PropertyChangedEventHandler PropertyChanged;  
      protected void OnPropertyChanged(string propertyName)  
      {  
           if (PropertyChanged != null)  
           {  
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
           }  
      }  
      #endregion  
 }  
и xaml разметку
 <Window x:Class="StaticFeaturesApp.MainWindow"  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
           xmlns:local="clr-namespace:StaticFeaturesApp"  
           SizeToContent="WidthAndHeight"  
     >  
      <Window.Resources>  
           <ResourceDictionary>  
                <local:SomeResource x:Key="SomeResourceOfApp"/>  
           </ResourceDictionary>  
      </Window.Resources>  
   <Grid>  
           <Grid.RowDefinitions>  
                <RowDefinition Height="Auto"/>  
                <RowDefinition Height="Auto"/>  
           </Grid.RowDefinitions>  
           <Grid.ColumnDefinitions>  
                <ColumnDefinition Width="Auto"/>  
                <ColumnDefinition Width="Auto"/>  
           </Grid.ColumnDefinitions>  
           <TextBlock HorizontalAlignment="Right" Text="StaticResource " Margin="5"/>  
           <TextBlock Grid.Column="1" HorizontalAlignment="Left" Margin="5"   
                       Text="{Binding NClicks, Source={StaticResource SomeResourceOfApp}}"/>  
           <Button Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Center" Margin="5" Padding="5,2,5,2"   
                     Content="Inc" Command="{Binding IncCommand, Source={StaticResource SomeResourceOfApp}}"/>  
      </Grid>  
 </Window>  
Этим чудесным свойством StaticResource иногда получается устроить биндинг в биндинге. Однако, полноценного связывания внутри другого связывания не получится, есть риск получить нестабильное поведение интерфейса. По нажатию на кнопку число NClicks будет увеличиваться и это отобразится на интерфейсе. Думаю, очевидно почему это так. Исходники здесь.

Комментариев нет:

Отправить комментарий