Пользовательский элемент управления Textbox в WPF неправильно связывает текст - PullRequest
2 голосов
/ 11 августа 2011

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

Ответы [ 2 ]

6 голосов
/ 11 августа 2011

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

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

Это говорит WPF «Эй, пожалуйста, ищите Стиль для этого элемента управления».

Теперь вы можете удалить x:Key="{x:Type TaskDash:TextBoxWithDescription}", потому что это будет ваш стиль по умолчанию.

Следующая вещь.В WPF важно понимать, что у каждого элемента управления нет абсолютно никакого пользовательского интерфейса, если только он не получает шаблон.У вас уже есть шаблон в вашем стиле, но единственным визуальным контентом, который он получает, является пустой текстовый ящик.Это странно, потому что вы выводите свой TextBoxWithDescription из TextBox.Итак, вы создаете элемент управления, полученный из текстового поля, содержащего текстовое поле.См. this , чтобы увидеть, как выглядит шаблон TextBox в WPF 4.0.

Вернуться к пустому TextBox в ControlTemplate.Помните, что я сказал, что ваши элементы управления без стиля совершенно невидимы, это единственная логика.Единственная видимая вещь - это TextBox в вашем шаблоне.Чтобы это как-то работало, вам нужно передать некоторые свойства этому TextBox.Элемент управления говорит, как и шаблон берет свойства и вводит их в действие.Вы можете сделать это через TemplateBinding Например.Если у вашего элемента управления есть Свойство Background, это свойство ничего не делает, вы можете установить его так долго, как хотите, но ControlTemplate может придать ему некоторое значение.Так, например, добавьте Rectangle в ControlTemplate и установите для свойства Fill значение {TemplateBinding Background}.Что в основном говорит Rectangle: «Ваше свойство Fill будет значением Background из элемента управления, который мы в настоящее время шаблонируем».Я надеюсь, что это ясно дает понять.

Следующая вещь: Вы переопределяете OnApplyTemplate, обычно вы делаете это, чтобы найти элемент управления в шаблоне ControlTemplate по имени.Кажется, вы смешали это с одним из ваших свойств.Чтобы найти элемент управления в вашем шаблоне через FindName, вам нужно дать ему имя

Как это

<Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TaskDash:TextBoxWithDescription}">

                        <TextBox x:Name="PART_MyTextBox">
                        </TextBox>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>

и изменить свой OnApplyTemplate на

var textBlock = (TextBlock)this.Template.FindName("PART_MyTextBox", this);

Теперь выУ вас есть текстовый блок в вашем текущем шаблоне ControlTemplate.

Последняя ошибка, которую я вижу, это.Вы устанавливаете OnApplyTemplate TextBox Text в свой LabelText.Хотя это работает, однажды, это не очень хорошо и обычно не так, как WPF.Кроме того, если вы измените свойство LabelText, оно не будет отображаться, поскольку вам придется установить его заново.Измените свой LabelText на свойство зависимости Теперь вы можете использовать уже упомянутый TemplateBinding для установки этого текста непосредственно в вашем шаблоне элемента управления TextBox.

                        <TextBox x:Name="PART_MyTextBox" Text="{TemplateBinding LabelText}>
                        </TextBox>

Это также гарантирует, чтоизменения в свойстве Control, также обновит текст в этом текстовом поле.

И последнее:

this.DataContext = taskItem;
        // textBoxDescription.DataContext = taskItem;
        _taskItem = taskItem;

Если ваше текстовое описание будет родительским для вашего окна, вы не будетенужно явно установить DataContext, потому что он будет наследоваться по иерархии.Пока Элемент не изменяет DataContext, он всегда будет DataContext родительского.

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

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

0 голосов
/ 12 августа 2011

@ dowhilefor - отличный ответ.Я пишу это как ответ только потому, что это будет слишком долго для комментария.

@ Шон - похоже, вы пытаетесь создать элемент управления Label-Field.Если это так, попробуйте этот шаблон:

<ControlTemplate TargetType="{x:Type TaskDash:TextBoxWithDescription}">
    <Grid>
        <Grid.ColumnDefinitions>
            <!--The SharedSizeGroup property will allow us to align all text boxes to the same vertical line-->
            <ColumnDefinition Width="Auto" 
                              SharedSizeGroup="LabelColumn"/>
            <!--This column acts as a margin between the label and the text box-->
            <ColumnDefinition Width="5"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Text="{TemplateBinding LabelText}"
                   VerticalAlignment="Center"/>
        <Border Grid.Column="2"
                Background="{TemplateBinding Background}"
                BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}">
            <ScrollViewer x:Name="PART_ContentHost"
                          Padding="{TemplateBinding Padding}"/>
        </Border>
    </Grid>
</ControlTemplate>

И удалите переопределение для OnApplyTemplate.

Если элемент управления является частью (часто называемой) PropertyGrid, и у вас есть несколькоДля экземпляров элемента управления TextBoxWithDescription на той же панели определите Grid.IsSharedSizeScope на этой панели (это не обязательно должна быть панель Grid).Это позволит выровнять текстовые поля по равномерной вертикальной линии.

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