Открытие нескольких источников привязки данных

Я чувствую, что мне не хватает довольно фундаментальной концепции WPF, когда дело доходит до привязки данных, но я не могу найти правильную комбинацию ключевых слов Google, чтобы найти то, что мне нужно, так что, возможно, сообщество SO может помочь. :)

У меня есть пользовательский элемент управления WPF, которому необходимо привязать данные к двум отдельным объектам для правильного отображения. Оба объекта должны быть динамически установлены из внешнего источника. До сих пор я просто использовал свойство DataContext формы для динамической привязки объекта, но это позволяет ссылаться только на один объект. Я чувствую, что это простая проблема, и я, должно быть, упускаю что-то очевидное.

Моя предыдущая попытка выглядит примерно так:

<UserControl.Resources>
    <src:Person x:Key = "personSource" />
    <src:Job x:Key = "jobSource" />
</UserControl.Resources>
<TextBox Text = "{Binding Source = {StaticResource personSource}, Path=Name" />
<TextBox Text = "{Binding Source = {StaticResource jobSource}, Path=Address" />

Это будет привязано к любым значениям по умолчанию, которые я даю классам, но если я попытаюсь динамически установить объекты в коде (как показано ниже), я не увижу никаких изменений.

Person personSource = FindResource("personSource") as Person;
personSource = externalPerson;
Job jobSource= FindResource("jobSource") as Job;
jobSource = externalJob;

Что мне не хватает?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
1 756
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я бы, вероятно, использовал CustomControl с двумя DependencyProperties. Затем внешний сайт, который использует ваш настраиваемый элемент управления, может привязать данные, которые они хотят, к этому элементу управления, а также с помощью настраиваемого элемента управления вы можете создать шаблон, как элемент управления выглядит в различных ситуациях.

Код настраиваемого элемента управления будет выглядеть примерно так:

public class CustomControl : Control
{
    public static readonly DependencyProperty PersonProperty =
        DependencyProperty.Register("Person", typeof(Person), typeof(CustomControl), new UIPropertyMetadata(null));
    public Person Person
    {
        get { return (Person) GetValue(PersonProperty); }
        set { SetValue(PersonProperty, value); }
    }


    public static readonly DependencyProperty JobProperty =
        DependencyProperty.Register("Job", typeof(Job), typeof(CustomControl), new UIPropertyMetadata(null));
    public Job Job
    {
        get { return (Job) GetValue(JobProperty); }
        set { SetValue(JobProperty, value); }
    }

    static CustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl), new FrameworkPropertyMetadata(typeof(CustomControl)));
    }
}

Generic.xaml - это файл, который должен быть создан для вас и может иметь стиль, который выглядит примерно так:

<ResourceDictionary
    xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local = "clr-namespace:WpfApplication3">


    <Style TargetType = "{x:Type local:CustomControl}">
        <Setter Property = "Template">
            <Setter.Value>
                <ControlTemplate TargetType = "{x:Type local:CustomControl}">
                    <Border Background = "{TemplateBinding Background}"
                            BorderBrush = "{TemplateBinding BorderBrush}"
                            BorderThickness = "{TemplateBinding BorderThickness}">
                        <StackPanel>
                            <TextBox Text = "{TemplateBinding Person.Name}" />
                            <TextBox Text = "{TemplateBinding Job.Address}" />
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Наконец, когда вы начнете использовать свой контроль, вы сделаете что-то вроде этого.

<src:CustomControl Person = "{Binding Person}" Job = "{Binding Job}" />

Кажется, это сработает, но теперь у меня другая проблема. Я действительно не хочу использовать стили для привязки этих элементов, но всякий раз, когда я пытаюсь сослаться на новое свойство зависимости, оно пытается найти его в тексте данных, а не в моем локальном объекте. Как я могу явно сослаться на локальное свойство?

Toji 04.11.2008 22:50

Не могли бы вы подробнее рассказать о том, как вы сейчас пытаетесь это сделать? Возможно, создайте новый вопрос, если он больше не актуален.

Todd White 04.11.2008 23:56

Хорошо, я решил это. И этот, и ответы Яна Оукса вместе - вот что решило эту проблему для меня, но, поскольку этот имеет более явный код, ответ идет к Тодду.

Toji 05.11.2008 00:37

Причина, по которой ваши текстовые поля не обновляются, заключается в том, что вы привязываете их к StaticResource. Как следует из названия, эти ресурсы статичны и не публикуют уведомления об изменениях. И поскольку Binding является MarkupExtension и не является производным от DependencyObject, вы не можете использовать DynamicResource.

Попробуйте создать в своем элементе управления свойства зависимости, чтобы ссылаться на объекты Person и Job.

Затем установите DataContext для UserControl так, чтобы он ссылался на себя.

DataContext = "{Binding RelativeSource = {RelativeSource Self}}"

Затем вы можете использовать точечную нотацию для ссылки на необходимые свойства.

<TextBox Text = "{Binding Path=Person.Name" />
<TextBox Text = "{Binding Path=Job.Address" />

Или используйте исходный параметр

<TextBox Text = "{Binding Source=Person, Path=Name" />
<TextBox Text = "{Binding Source=Job, Path=Address" />

Другие вопросы по теме