Search code examples
wpftabcontrolcontentpresenteruielement

control to interchange UIElements in WPF


What is the most minimal way to dynamically interchange UIElements at a certain "slot" on the UI? I have a number of UIElements and based on some external databinding (e.g. a combobox selection) I want one of them to be shown and the one that was currently visible to be hidden. So the behavior is sort of like the TabControl but without the tabstrip, the chrome and the tabitem instances. So I could actually use the TabControl and override the control template. But is this really the most minimal approach?


Solution

  • You have several options. As Bryan mentioned, Data Template Selectors can definitely work, although I've decided that they are frequently overkill. Take your example for instance - if you want to bind the visibility of an element to the selection in a ComboBox, I would prefer a ValueConverter instead. Pass the ComboBox.SelectedItem to the Converter and have it return a Visibility value:

    public class MyObjectToVisibleOrCollapsed : IValueConverter
    {
        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is MyObject)
            {
                var myObject = (MyObject)value;
                if (myObject.SomeState)
                {
                    return Visibility.Visible;
                }
            }
    
            return Visibility.Collapsed;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    
        #endregion
    }
    

    Now in your Window.Resources, create an instance of the ValueConverter and Bind the Element to the ComboBox.SelectedItem using the ValueConverter instance:

    <local:MyObjectToVisibleOrCollapsed x:Key="myObjectToVisibleOrCollapsed"/>
    <DataTemplate x:Key="MyTemplate">
        <TextBlock Text="{Binding Path=myText}" 
                   x:Name="MyText" 
                   Visibility="{Binding ElementName=MyComboBox, Path=SelectedItem, Converter={StaticResource myObjectToVisibleOrCollapsed}, Mode=Default}" />
    </DataTemplate>
    

    And of course you can reuse the ValueConverter for all the elements in your DataTemplate (and if there are a lot of them, then the Data Template Selector approach becomes more desirable).

    [Disclaimer: the code above was hashed out from memory and not tested - it may need a little tweaking]