WPF ComboBox изначально отображает первый элемент в неправильном размере - PullRequest
1 голос
/ 06 июля 2011

У меня есть ComboBox в окне WPF, которое вызывает у меня душевную боль, потому что при первом отображении первый выбор отображается неправильно.ComboBox не отображает только текст;он отображает объект типа, который происходит от UserControl.Вот XAML для самого ComboBox:

<ComboBox Grid.Column="0" 
          Height="69" 
          HorizontalAlignment="Stretch"
          HorizontalContentAlignment="Center"
          ItemsSource="{Binding Path=ViewChoices, 
                        RelativeSource={RelativeSource AncestorType={x:Type UserControl}},  
                        Mode=OneWay}" 
          Margin="10" 
          Name="ViewPicker" 
          SelectionChanged="ViewPicker_SelectionChanged" 
          VerticalAlignment="Stretch" 
          VerticalContentAlignment="Center" />

Как вы можете видеть, ItemsSource ComboBox связан со свойством UserControl, которому он принадлежит, и называется ViewChoices.Объект ViewChoices - это ObservableCollection.

Содержимое ComboBox задается в коде в следующем коде, поскольку точное содержимое в конечном коде будет считываться из файла XML;значения прямо сейчас жестко запрограммированы.По сути, объект CameraViewChoice создается для каждой прочитанной строки XML и добавляется в коллекцию ViewChoices.Все это происходит в конструкторе по умолчанию UserControl, после вызова InitializeComponent ().В обработчике событий Loaded UserControl у меня есть код, который устанавливает свойство SelectedIndex ComboBox равным 0.

Объект CameraViewChoice происходит от UserControl.Вот Xaml для этого элемента управления:

<UserControl x:Class="CarSystem.CustomControls.CameraViewChoice"
             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:cs="clr-namespace:CarSystem.CustomControls"  
             mc:Ignorable="d" 
             d:DesignHeight="50" d:DesignWidth="50">

    <Border BorderBrush="Black" BorderThickness="1">
        <Grid>
            <Image Opacity="0.35" Source="..." Stretch="Uniform" />
            <Label Content="{Binding Path=Text}" 
                   FontSize="18" 
                   FontWeight="Bold" 
                   Foreground="White" 
                   HorizontalAlignment="Center" 
                   VerticalAlignment="Center" />
        </Grid>
    </Border>

</UserControl>

Вот код для объекта CameraViewChoice:

public partial class CameraViewChoice : UserControl {

    public static readonly DependencyProperty AttachedCameraProperty =  DependencyProperty.Register( "AttachedCamera", typeof( Camera ), typeof( CameraViewChoice ), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.AffectsRender ) );

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof( string ), typeof( CameraViewChoice ), new FrameworkPropertyMetadata( string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsParentMeasure | FrameworkPropertyMetadataOptions.AffectsRender ) );

    public Camera AttachedCamera {
        get { return (Camera) GetValue( AttachedCameraProperty ); }
        set { SetValue( AttachedCameraProperty, value ); }
    }

    public string Text {
        get { return (string) GetValue( TextProperty ); }
        set { SetValue( TextProperty, value ); }
    }

    public CameraViewChoice() {
        InitializeComponent();
    }

Это все работает нормально, но есть одна проблема.Когда программа запускается и ComboBox отображается в первый раз, выбранный элемент отображается неправильно.Метка пуста, а элемент управления CameraViewChoice отображается слишком большим, так что его нижняя часть обрезается.То, что я вижу, - это пустой объект CameraViewChoice, отображаемый без масштабирования до ComboBox.

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

У кого-нибудь есть идеи по поводу того, что происходит?

Тони

Редактировать:

Я сделалнекоторые исследования в журнале Google и MSDN, и я нашел статью Джоша Смита о шаблонах данных.Оттуда я внес следующие изменения в XAML для моего ComboBox:

<ComboBox Grid.Column="0" 
          Height="69" 
          HorizontalAlignment="Stretch"
          HorizontalContentAlignment="Center"
          ItemsSource="{Binding Path=ViewChoices, 
                        RelativeSource={RelativeSource AncestorType={x:Type UserControl}},  
                        Mode=OneWay}" 
          Margin="10" 
          Name="ViewPicker" 
          SelectionChanged="ViewPicker_SelectionChanged" 
          VerticalAlignment="Stretch" 
          VerticalContentAlignment="Center">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <cs:CameraViewChoice Margin="10" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Это лучше, поскольку элементы в ComboBox не меняют размер, но начальный экран все еще слишком велик.То есть оно отрезано внизу.Кроме того, размер выбранного элемента постоянно слишком велик.Поэтому, когда вы выбираете один элемент в списке, он отображается в поле со списком частично обрезанным.

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

Ответы [ 2 ]

1 голос
/ 06 июля 2011

В событии Loaded, если у вас есть как минимум 2 элемента, задайте для SelectedIndex значение 1. После этого, независимо от того, сколько элементов у вас есть, вызовите InvalidateMeasure и UpdateLayout в ComboBox, а затем установите SelectedIndex на 0.

1 голос
/ 06 июля 2011

Вот что, я думаю, происходит.

Вы используете стандартный ComboBox и динамически добавляете в него элементы UIE.Когда ComboBox отображается впервые, элементов нет, поэтому он использует шаблон по умолчанию.После того, как вы начнете добавлять элементы UIElements, рендерер выполнит измерение и упорядочение.По сути, он только изучает, как он должен выглядеть после того, как элементы UIE созданы и вставлены (но все еще нужно было знать, как он должен выглядеть до того, как это произошло).

Мое предложение состоит в том, чтобы отказаться от этого шаблона разработки.к более общей методологии.Вместо создания UIElements на лету, просто создайте ObservableCollection CameraChoices (или любое другое имя, которое будет подходящим).Обычно это содержится в ViewModel.

Тогда вместо создания UserControl и вставки его в ItemsSource ComboBox вам лучше будет создать ItemTemplate (где вы можете использовать UserControl) дляComboBox.В качестве альтернативы вы можете использовать DataTemplate того же типа, что и объект в ObservableCollection.

Это обеспечит более надежный механизм для отображения списка элементов и даст вам возможность вместо этого получить необработанные данныенеобходимости иметь дело с UIElement, когда сигнализируется событие SelectionChanged.

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