czwartek, 16 sierpnia 2012

[WPF] Attached Property

Attached Property to nic innego jak Dependency Property dołączane do obiektów już istniejących. Jest to na przykład świetny sposób na rozszerzanie kontrolek z których nie można dziedziczyć, lub z których dziedziczyć się nie opłaca, bo chcemy dodać tylko jedną prostą funkcjonalność. Przykładem AP jest Grid.Column ustawiane dla elementów potomnych. Ustawia się je w celu poinformowania rodzica o tym, jak mają być ustawione dzieci. Ogólnie założeniem AP jest, by klasy zgromadzone w pewien sposób w hierarchii lub powiązane w pewien logiczny sposób mogły zgłaszać wspólną informację do typu, które definiuje Attached Property. Typ ten może być zdefiniowany, jako rodzic, zawierający wiele dzieci. Iterując po nich może on wyciągać informacje, które go interesują. Inne zastosowanie, to serwis, który jest powiadamiany w momencie, gdy AttachedProperty jest ustawiane.

W poniższym przykładzie stworzono serwis, kontrolujący to, który prostokąt został wybrany. Attached Property rejestrowane jest podobnie jak Dependency Property specjalną metodą RegisterAttached.

<Window x:Class="Attached_Property.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Attached_Property="clr-namespace:Attached_Property" Title="MainWindow" Height="200" Width="200">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Rectangle Width="100" Height="100" MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect1" Stroke="Red" Grid.Column="0" Grid.Row="0" 
                   Fill="LightGreen" Attached_Property:RectangleService.IsChecked="True" />
        <Rectangle Width="100" Height="100"  MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect2" Stroke="Red" Grid.Column="1" Grid.Row="0" />
        <Rectangle Width="100" Height="100" MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect3" Stroke="Red" Grid.Column="0" Grid.Row="1" />
        <Rectangle Width="100" Height="100" MouseEnter="Rect3_MouseEnter"
                   x:Name="Rect4" Stroke="Red" Grid.Column="1" Grid.Row="1" />
    </Grid>
</Window>


 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Rect3_MouseEnter(object sender, MouseEventArgs e)
        {
            RectangleService.SetIsChecked(sender as DependencyObject, true);
        }
    }


 public class RectangleService
    {
        public static readonly DependencyProperty IsCheckedProperty;

        public static Rectangle CheckedRect { get; set; }

        static RectangleService()
        {
            IsCheckedProperty = DependencyProperty.RegisterAttached("IsChecked"
                              typeof (bool), typeof (Rectangle),
                                                new PropertyMetadata(false));
        }

        public static void SetIsChecked(DependencyObject element, bool value)
        {
            element.SetValue(RectangleService.IsCheckedProperty, value);
            //service logic
            if (!value) return;
            if(CheckedRect != null)
                CheckedRect.Fill = new SolidColorBrush(Colors.Yellow);
            CheckedRect = element as Rectangle;
            if(CheckedRect== null)
                return;
            CheckedRect.Fill = new SolidColorBrush(Colors.LightGreen);
        }

        public static bool GetIsChecked(DependencyObject element)
        {
            return (bool)element.GetValue(RectangleService.IsCheckedProperty);
        }

Brak komentarzy:

Prześlij komentarz