Vishal
Vishal

Reputation: 6368

Binding Visibility of a ComboBox to Multiple Properties

Suppose I have a Window named MainWindow.xaml and a Page named Page.xaml.

On MainWindow.xaml :

I have a Menu and a Frame. In this Frame Page.xaml is displayed.

DataContext of MainWindow.xaml is bound to MainWindowViewModel.

I have a property called SelectedMenuItem of type int on MainWindowViewModel.

So, Menu's SelectedItem is bound to SelectedMenuItem.

On Page.xaml :

I have 2 ComboBoxes named Combo1 and Combo2.

Now I want to bind Visibility of Combo2 to somthing.

The required Behavior :

Combo2 should be visible when Combo1's first item is selected && SelectedMenuItem = 1.

So, How should I bind Combo2's Visibility?

Update :

According to your answer, I have tried to implement IMultiValueConverter like below code:

EffectsVisibilityConverter.cs

public class EffectsVisibilityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(values[0] == null || values[1] == null))
        {
            if (((int)values[0] == 1) && ((int)values[1] == 1))
            {
                return Visibility.Visible;
            }
            else
            {
                return Visibility.Collapsed;
            }
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

In Page.xaml :

<ComboBox ItemsSource="{Binding DataContext.Effects, RelativeSource={RelativeSource AncestorType={x:Type Page}}}"  
          DisplayMemberPath="Effect" SelectedValue="{Binding EffectID}" SelectedValuePath="EffectID">
    <ComboBox.Visibility>
        <MultiBinding Converter="{StaticResource effectsVisibilityConverter}">
            <Binding Path="SelectedParent" >
                <Binding.Source>
                    <vm:MainWindowViewModel />
                </Binding.Source>
            </Binding>
            <Binding Path="DataContext.SelectedGroupID" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}" />
        </MultiBinding>
    </ComboBox.Visibility>
</ComboBox>

But problem is that, the value of values[0] in Converter always remains 0.

Upvotes: 0

Views: 1384

Answers (3)

WPFUser
WPFUser

Reputation: 1175

Using MultiBinding and Converter :instead of menuitem I've used Checkbox's IsChecked

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:NameConverter x:Key="NameConverter"/>
    </Window.Resources>
    <Grid>

        <ComboBox x:Name="cbox1" VerticalAlignment="Center" Text="3"   MinHeight="20">
            <ComboBoxItem  Content="first" />
            <ComboBoxItem  Content="second"/>
            <ComboBoxItem  Content="third"/>
            <ComboBoxItem  Content="fourth"/>
        </ComboBox>

        <ComboBox VerticalAlignment="Bottom" Text="3"   MinHeight="20" >
            <ComboBox.Visibility>
                <MultiBinding Converter="{StaticResource NameConverter}">
                    <Binding Path="SelectedItem" ElementName="cbox1"/>
                    <Binding Path="IsChecked" ElementName="chkbox"/>
                </MultiBinding>
            </ComboBox.Visibility>
            <ComboBoxItem  Content="1" />
            <ComboBoxItem  Content="2"/>
            <ComboBoxItem  Content="3"/>
            <ComboBoxItem  Content="4"/>
            </ComboBox>
        <CheckBox x:Name="chkbox" Content="Isselected" HorizontalAlignment="Left" Margin="10,56,0,0" VerticalAlignment="Top"/>

    </Grid>
</Window>



public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

public class NameConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if ((values[0] is ComboBoxItem) && (values[0] as ComboBoxItem).Content.ToString() == "first" && (bool)values[1])

            return Visibility.Visible;
        else return Visibility.Collapsed;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return null;
    }
}

update//

<ComboBox.Visibility>
    <MultiBinding Converter="{StaticResource NameConverter}">
        <Binding Path="SelectedItem" ElementName="cbox1"/>
        <Binding  Path="IsChecked">
            <Binding.RelativeSource >
                <RelativeSource Mode="FindAncestor" AncestorType="{x:Type Window}" />
            </Binding.RelativeSource>

        </Binding>
    </MultiBinding>
</ComboBox.Visibility>

Upvotes: 1

Mighty Badaboom
Mighty Badaboom

Reputation: 6155

You can use a IMultiValueConverter and bind e.g. SelectedMenuItem and Combo1.SelectedIndex to the converter to determine the visibility of Combo2.

I would prefere this way instead of creating new viewmodel properties because it's pure ui logic and has nothing to do with the viewmodels logic.

//Edit

Why you don't use the binding like Kuna wrote?

<MultiBinding Converter="{StaticResource NameConverter}">
    <Binding Path="SelectedItem" ElementName="cbox1"/>
    <Binding Path="IsChecked" ElementName="chkbox"/>
</MultiBinding>

Just use SelectedIndex instead of SelectedItem and everything's fine.

Upvotes: 2

GazTheDestroyer
GazTheDestroyer

Reputation: 21251

Just add another property to your viewmodel and do the logic in there.

Upvotes: 0

Related Questions