Тип свойства зависимости не соблюдается - PullRequest
0 голосов
/ 19 апреля 2020

Почему свойство зависимости с типом XXX может получить значение другого типа?

Является ли тип свойства зависимости, только что определенный для значения по умолчанию?

Например:

Структура проекта:

Project

Код управления пользователем (CarControl):

XAML-код:

<UserControl x:Class="TypeOfDependencyProperty.Controls.CarControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock Text="{Binding Brand}"/>
    </Grid>
</UserControl>

Код (C#):

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

namespace TypeOfDependencyProperty.Controls
{
    public partial class CarControl : UserControl
    {
        #region Brand

        public static readonly DependencyProperty BrandProperty =
            DependencyProperty.Register("Brand", typeof(string), typeof(CarControl),
                new FrameworkPropertyMetadata((string)string.Empty));

        public string Brand
        {
            get { return (string)GetValue(BrandProperty); }
            set { SetValue(BrandProperty, value); }
        }

        #endregion

        public CarControl()
        {
            InitializeComponent();
        }
    }
}

Обратите внимание, что это свойство зависимости Brand имеет тип string здесь.

Просмотр кода (CarView):

Код XAML:

<Page x:Class="TypeOfDependencyProperty.Views.CarView"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:controls="clr-namespace:TypeOfDependencyProperty.Controls"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="CarView">
    <Grid>
        <controls:CarControl Brand="{Binding Brand}"/>
    </Grid>
</Page>

Код позади (C#):

using System.Windows.Controls;
using TypeOfDependencyProperty.ViewModels;

namespace TypeOfDependencyProperty.Views
{
    public partial class CarView : Page
    {
        public CarView()
        {
            InitializeComponent();
            this.DataContext = new CarViewModel();
        }
    }
}

Просмотр кода модели (CarViewModel):

namespace TypeOfDependencyProperty.ViewModels
{
    public class CarViewModel
    {
        public string Brand { get; set; }
        public CarViewModel()
        {
            Brand = "XXXXXXXXXXXXXXXXXXXXXXXXX"; // Any value
        }
    }
}

Теперь, если я измените тип с string на List<XXX> (или другой), как показано ниже, он продолжает работать.

#region Brand

public static readonly DependencyProperty BrandProperty =
    DependencyProperty.Register("Brand", typeof(List<double>), typeof(CarControl),
        new FrameworkPropertyMetadata((List<double>)null));

public List<double>Brand
{
    get { return (List<double>)GetValue(BrandProperty); }
    set { SetValue(BrandProperty, value); }
}

#endregion

Конечно, я получаю следующую ошибку в окне вывода, но она все еще работает! Значение отображается без сбоев при запуске.

System. Windows .Data Ошибка: 1: Невозможно создать конвертер по умолчанию для выполнения односторонних преобразований между типами System.String и 'System.Collections.Generi c .List 1[System.Double]'. Consider using Converter property of Binding. BindingExpression:Path=Brand; DataItem='CarViewModel' (HashCode=14000148); target element is 'CarControl' (Name=''); target property is 'Brand' (type 'List 1')

System. Windows .Data Ошибка: 5: значение, созданное BindingExpression, недопустимо для целевого свойства .; Значение = 'Марка автомобиля' BindingExpression: Path = Brand; DataItem = 'CarViewModel' (HashCode = 14000148); целевым элементом является 'CarControl' (Name = ''); целевым свойством является 'Бренд' (тип 'Список`1')

Может кто-нибудь объяснить мне? Это ошибка?

Ответы [ 3 ]

1 голос
/ 19 апреля 2020

Привязка в

<TextBlock Text="{Binding Brand}"/>

связывает непосредственно со свойством Brand в модели представления. Он не использует свойство Brand элемента управления.

Таким образом, он даже отображает значение свойства модели представления при записи

<controls:CarControl />

без привязки свойства Brand элемента управления вообще.

Правильное использование свойства элемента управления в XAML элемента управления будет следующим:

<TextBlock Text="{Binding Brand,
                  RelativeSource={RelativeSource AncestorType=UserControl}}"/>
0 голосов
/ 19 апреля 2020

Тип DependecyProperty определяет тип данных, хранящихся в нем. Вы можете привязать к нему только один и тот же тип данных. Или вы можете добавить конвертер для привязки. Для этого вам нужно реализовать интерфейс IValueConverter .

Но я не понимаю вашей проблемы, хотите, чтобы вы отобразили весь список в строке? Или вы хотите создать элемент для каждого элемента списка?

Во втором случае я предлагаю вам использовать ItemsControl и вставить свой собственный элемент управления в ItemTemplate .

* 1010. * Наконец, вам не нужно каждый раз определять значение по умолчанию, вы можете удалить PropertyMetadata из инициализации DependecyProperty. И помните, если вы определите его там, это будет stati c и будет меняться от других экземпляров только с базовыми типами. Если у вас есть класс, я предлагаю вам использовать null и назначить его в классе Costructor.
public static readonly DependencyProperty BrandProperty =
    DependencyProperty.Register("Brand", typeof(List<double>), typeof(CarControl));
0 голосов
/ 19 апреля 2020

Когда вы говорите «получить значение»

in:

Почему свойство зависимости с типом XXX может получить значение другого типа?

То, о чем вы спрашиваете, - это действительно то, как разрешается привязка.

Инфраструктура WPF разрешает привязку и получает фактическое текущее значение.

Когда она завершится, инфраструктура попытается «установить» значение для вашего свойства зависимостей, и только тогда он проверит, совпадают ли типы.

Если они не совпадают и преобразователь не был предоставлен для привязки, он выдаст добавленное вами исключение ,

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