Как свойства зависимости работают в WPF? - PullRequest
0 голосов
/ 06 мая 2020

Я пытаюсь понять свойство зависимости и научиться его использовать. Я просматриваю статьи, и в этой статье https://www.c-sharpcorner.com/UploadFile/6d590d/wpf-dependency-property/ есть такой пример:

MainWindow.xaml:

<Window x:Class="WpfApplication1.DependencyPropertyDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="DependencyPropertyDemo" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <local:CarDependencyClass x:Key="carDependencyClass"></local:CarDependencyClass>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Label Content="Enter Car:" Grid.Row="0" VerticalAlignment="Center" />
        <TextBox Text="{Binding Path=MyCar, Source={StaticResource carDependencyClass }}" Name="MyTextCar" Height="25" Width="150" />
        <Button Name="MyButton" Content="Click Me!" Height="25" Click="MyButton_Click" Width="150" Grid.Row="1" />
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;


namespace WpfApplication1 {
    /// <summary>  
    /// Interaction logic for DependencyPropertyDemo.xaml  
    /// </summary>  
    public partial class DependencyPropertyDemo : Window {
        public DependencyPropertyDemo() {
            InitializeComponent();
        }
        private void MyButton_Click(object sender, RoutedEventArgs e) {
            CarDependencyClass dpSample = TryFindResource("carDependencyClass") as CarDependencyClass;
            MessageBox.Show(dpSample.MyCar);
        }
    }
    public class CarDependencyClass : DependencyObject {
        //Register Dependency Property  
        public static readonly DependencyProperty CarDependencyProperty = DependencyProperty.Register("MyProperty", typeof(string), typeof(CarDependencyClass));
        public string MyCar {
            get {
                return (string)GetValue(CarDependencyProperty);
            }
            set {
                SetValue(CarDependencyProperty, value);
            }
        }
    }
}

Работает. Я заметил, что они зарегистрировали свойство зависимости с именем «MyProperty» и что оно нигде в программе не используется. В xaml используется только обычное свойство среды CLR MyCar.

Но есть еще одна статья https://www.c-sharpcorner.com/article/simplest-wpf-dependency-property-for-beginners-on-background-color/. И они предоставляют другой пример:

MainWindow.xaml:

<Window x:Class="DependencyPropertyTutorial.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:views="clr-namespace:DependencyPropertyTutorial" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:DependencyPropertyTutorial" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <SolidColorBrush x:Key="BG" Color="Green" />
    </Window.Resources>
    <Grid>
        <views:CustomButtonControl SetBackground="{DynamicResource BG}"></views:CustomButtonControl>
    </Grid>
</Window>

CustomButtonControl.xaml:

<UserControl x:Class="DependencyPropertyTutorial.CustomButtonControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DependencyPropertyTutorial"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button x:Name="btnCustom" Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Height="52" Click="btnCustom_Click" />
    </Grid>
</UserControl>

CustomButtonControl.xaml.cs:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;


namespace DependencyPropertyTutorial {
    /// <summary>  
    /// Interaction logic for CustomButtonControl.xaml  
    /// </summary>  
    public partial class CustomButtonControl : UserControl {
        public CustomButtonControl() {
            InitializeComponent();
        }
        public static readonly DependencyProperty btnDependencyProperty = DependencyProperty.Register("SetBackground", typeof(SolidColorBrush), typeof(CustomButtonControl), new PropertyMetadata(new SolidColorBrush(Colors.HotPink), new PropertyChangedCallback(OnSetColorChanged)));
        public SolidColorBrush SetBackground {
            set {
                SetValue(btnDependencyProperty, value);
            }
            get {
                return (SolidColorBrush)GetValue(btnDependencyProperty);
            }
        }
        private void btnCustom_Click(object sender, RoutedEventArgs e) {
            this.SetBackground = new SolidColorBrush(Colors.IndianRed);
        }
        private static void OnSetColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            CustomButtonControl mycontrol = d as CustomButtonControl;
            mycontrol.callmyInstanceMethod(e);
        }
        private void callmyInstanceMethod(DependencyPropertyChangedEventArgs e) {
            btnCustom.Background = (SolidColorBrush)e.NewValue;
        }
    }
}

И здесь они регистрируют свойство зависимости с именем "SetBackground", которое в точности совпадает с именем свойства CLR - SetBackground. И если я изменю свойство зависимости (то, которое я зарегистрировал с помощью метода Register) «SetBackground» на что-то другое, например «SetBackgroundDependencyProperty», то при попытке запустить приложение я получаю исключение XAML. Но свойство зависимостей SetBackground нигде даже не упоминается в xaml. Только свойство CLR SetBackground упоминается в XAML в строке

<views:CustomButtonControl SetBackground="{DynamicResource BG}"></views:CustomButtonControl>

Я также получаю сообщение об ошибке в Visual Studio в этом примере: enter image description here

Но когда я пытаюсь собрать и запустить приложение, оно работает.

Итак, у меня следующие вопросы: почему в первом примере им не нужно было называть зарегистрированное свойство зависимости так же, как свойство CLR, но во втором примере я должен назвать зарегистрированное свойство зависимости так же, как свойство CLR. Есть ли способ назвать зарегистрированное свойство зависимостей иначе, чем свойство CLR во втором примере? Почему и как xaml даже использует свойства зависимостей, учитывая, что xaml все равно ссылается только на свойства CLR? Я проверил это, и в обоих проектах только на свойства CLR ссылаются из XAML, согласно VS IntelliSense. Почему мне нужно регистрировать свойство зависимости с тем же именем, что и свойство CLR - «SetBackground», когда в xaml указывается только свойство CLR, и оно все равно возвращает SolidColorBru sh из свойства зависимости:

return (SolidColorBrush)GetValue(btnDependencyProperty);

Вот решение для обоих примеров: https://github.com/KulaGGin/DependencyProperty

Ответы [ 3 ]

1 голос
/ 07 мая 2020

Первый пример немного грязный, я бы не стал его так кодировать. Существует хорошее соглашение, чтобы избежать путаницы - назвать DP как свойство CLR + 'Property' (, но это не обязательно! ) и зарегистрировать его как имя свойства CLR (, если хотите чтобы использовать его как DP в XAML ).
Сначала к вашим вопросам:

  • Первый пример работает, потому что везде, где используется свойство MyCar, оно используется как свойство CLR. Если вы попытаетесь выполнить привязку к MyCar, это не удастся, поскольку такого свойства зависимости нет. Для реализации функциональности в этом примере будет достаточно просто объявить свойство CLR:
    public string MyCar { get; set; }
    вместо всей этой путаницы со свойством зависимостей.
  • Во втором примере определяется свойство CLR, а также свойство зависимости SetBackground (имя btnDependencyProperty для поля неудобно, но нормально). Непонимание с вашей стороны, это то, что используется в XAML.
    Если вы используете в XAML Binding или DynamicResource свойство зависимостей, а также свойство CLR, необходимы! Следовательно, они должны иметь то же имя. В противном случае вы получите сообщение об ошибке.
    Если вы установите для свойства значение StaticResource или непосредственно значение или даже не используете его в XAML, вы сможете запустить приложение.
1 голос
/ 07 мая 2020

Реализация DependencyProperty немного странная.

Компилятор XAML зависит от оболочки свойств CLR для компиляции, но во время привязки во время выполнения игнорирует ее полностью и просто вызывает GetValue / SetValue на DP. Поэтому имена должны совпадать.

0 голосов
/ 06 мая 2020

В первом примере была опечатка. Имя зарегистрированного свойства зависимости должно быть таким же, как свойство поддержки CLR.

Объявление DependencyProperty - это двухэтапный процесс:

  1. Зарегистрируйте свойство, чтобы WPF DependencyProperty система может отслеживать его и уведомлять об изменении свойств, et c.
  2. Установите свойство CLR, которое дает разработчикам API для получения и установки значений.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...