我在WPF窗口上有一个ComboBox给了我一些心痛,因为在第一次显示时,第一个选择被不正确地呈现。 ComboBox不显示文本;它显示一个从UserControl下降的类型的对象。这是ComboBox本身的XAML:
<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的ItemsSource绑定到拥有它的UserControl属性ViewChoices。 ViewChoices对象是一个ObservableCollection。
ComboBox的内容在后面的代码中的代码中设置,因为最终代码中的确切内容将从XML文件中读取;这些值现在是硬编码的。实质上,为读取的每个XML行创建一个CameraViewChoice对象,并将其添加到ViewChoices集合中。这一切都发生在UserControl的默认构造函数中,在调用InitializeComponent()之后。在UserControl的Loaded事件处理程序中,我有代码将ComboBox的SelectedIndex属性设置为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&amp; amp;做了一些研究。 MSDN杂志和我发现了Josh Smith关于数据模板的一篇文章。从那里,我对我的ComboBox的XAML进行了以下更改:
<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中显示的选项,其中所有选项都适合它。有关更改CombobBox的ItemTemplate的建议吗?
答案 0 :(得分:1)
这就是我认为正在发生的事情。
您正在使用标准ComboBox并动态添加UIElements。首次显示ComboBox时,没有项目,因此它使用默认模板。在您开始向其添加UIElements之后,渲染器会执行测量和排列。从本质上讲,它只是在创建和插入UIElements后才能学习它应该是什么样子(但它仍然需要知道在发生之前看起来像什么)。
我的建议是从这种发展模式转向更常见的方法。而不是动态创建UIElements,只需创建一个ObservableCollection的CameraChoices(或任何适当的名称)。通常,这将包含在ViewModel中。
然后,不是创建UserControl并将其插入到ComboBox的ItemsSource中,而是更好地为ComboBox创建ItemsTemplate(您可以在其中使用UserControl)。或者,您可以使用与ObservableCollection中的对象相同类型的DataTemplate。
这将为显示项目列表提供更强大的机制,并为您提供获取原始数据的方法,而不是在发出SelectionChanged事件时必须处理UIElement。
答案 1 :(得分:1)
在Loaded事件中,如果您至少有2个项目,请将SelectedIndex设置为1.在此之后,无论您有多少项目,请在ComboBox上调用InvalidateMeasure和UpdateLayout,然后将SelectedIndex设置为0。