WPF自定义ComboBox初始值设置

3

我已经创建了一个自定义ComboBox,当ReadOnly属性被设置时,它将显示为一个TextBox:

<local:BoolToVisibilityConverter FalseValue="Hidden" TrueValue="Visible" x:Key="BoolVis" />
<local:BoolToVisibilityConverter FalseValue="Visible" TrueValue="Hidden" x:Key="BoolVisRev" />

<Style TargetType="{x:Type local:ComboBoxG}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ComboBoxG}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <Grid>
                        <ComboBox ItemsSource="{TemplateBinding ItemsSource}"
                                  DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
                                  SelectedValuePath="{TemplateBinding SelectedValuePath}"
                                  SelectedIndex="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedIndex, Mode=TwoWay}"
                                  Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsReadOnly, Converter={StaticResource BoolVisRev}}"
                                  IsDropDownOpen="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsDropDownOpen, Mode=TwoWay}"
                                  IsTabStop="False">
                        </ComboBox>
                        <TextBox Text="{TemplateBinding Text}" 
                                 Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsReadOnly, Converter={StaticResource BoolVis}}"
                                 IsTabStop="False">
                        </TextBox>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

除了一种情况,它运行良好,即如果我一次性实例化并设置值。这种方法不起作用...

private void One_OnClick(object sender, RoutedEventArgs e)
{
    cmb = new ComboBoxG();
    Stack.Children.Add(cmb);

    var dict = new Dictionary<int, string> { { 0, "aaa" }, { 1, "bbb" }, { 2, "ccc" }, { 3, "ddd" }, };
    cmb.ItemsSource = dict;
    cmb.DisplayMemberPath = "Value";
    cmb.SelectedValuePath = "Key";
    cmb.SelectedValue = 3;
}

相反,这个操作会...

private void One_OnClick(object sender, RoutedEventArgs e)
{
    cmb = new ComboBoxG();
    Stack.Children.Add(cmb);

    var dict = new Dictionary<int, string> { { 0, "aaa" }, { 1, "bbb" }, { 2, "ccc" }, { 3, "ddd" }, };
    cmb.ItemsSource = dict;
    cmb.DisplayMemberPath = "Value";
    cmb.SelectedValuePath = "Key";
    cmb.Loaded += cmb_Loaded;
}

private void cmb_Loaded(object sender, RoutedEventArgs e)
{
    cmb.SelectedValue = 3;
}

我可以绕过它,但对于这个控件的某些使用来说会变得很尴尬。有什么建议吗?

3个回答

1
我之前也遇到过这个问题,目前唯一的半愉快解决方法是让消息队列通过Loaded阶段排干。请注意,我对此并不感到自豪,但WPF会分阶段执行某些操作,有时你希望将所有内容放在一起。你可以将cmd.SelectedValue = 3放入委托中,但这只是个人喜好...
        cmb = new ComboboxG();
        theStack.Children.Add(cmb);

        var dict = new Dictionary<int, string> { { 0, "aaa" }, { 1, "bbb" }, { 2, "ccc" }, { 3, "ddd" }, };
        cmb.ItemsSource = dict;
        cmb.DisplayMemberPath = "Value";
        cmb.SelectedValuePath = "Key";

        Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.Loaded);

        cmb.SelectedValue = 3;

请注意,这将允许事件运行,因此要小心避免重入!


谢谢,我很高兴不只有我一个人遇到这个问题。这是一个很好的解决方案示例。对于我大部分实际情况来说,值将来自于绑定,所以解决方法就是改变绑定发生的时间。很抱歉我不能给你的答案点赞,因为我还没有足够的声望点数。 - johndsamuels

0
你试过设置选中索引吗?
private void One_OnClick(object sender, RoutedEventArgs e)
{
    cmb = new ComboBoxG();
    Stack.Children.Add(cmb);

    var dict = new Dictionary<int, string> { { 0, "aaa" }, { 1, "bbb" }, { 2, "ccc" }, { 3, "ddd" }, };
    cmb.ItemsSource = dict;
    cmb.DisplayMemberPath = "Value";
    cmb.SelectedValuePath = "Key";
    cmb.SelectedIndex = 3;
}

1
是的,行为完全相同。 - johndsamuels

0
尝试设置SelectedItem而不是Index

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接