Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF custom ComboBox initial value setting

I've built a custom ComboBox which shows as a TextBox when ReadOnly is set:

<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>

It's working fine, other than if I instantiate and set a value all in one go. This doesn't work ...

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;
}

... whereas this does ...

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;
}

So I can work around it but it is making it awkward for some uses of this control. Any suggestions, please?

like image 806
johndsamuels Avatar asked Sep 04 '26 04:09

johndsamuels


1 Answers

I've run into this before as well and so far the only semi-pleasant workaround to do this all in one method is to let the message queue drain through the Loaded stage. Note, I'm not proud of this but WPF does things in stages and sometimes you'd prefer to have everything together. You could put the cmd.SelectedValue = 3 into the delegate I suppose but it's a matter of taste...

        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;

Beware that this will allow events to run so be careful of reentrancy!

like image 194
jschroedl Avatar answered Sep 08 '26 06:09

jschroedl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!