Search code examples
wpfdata-bindingmultibinding

Databinding one property on a Dialog from two contols


I have a Window that I'm showing using ShowDialog. One of the values I'm trying to get from the user is size in GB or TB. So I have two controls for this, an IntegerUpDown from the WPF Extended Toolkit and a ComboBox:

<xctk:IntegerUpDown Name="SizeN" Minimum="1" Maximum="1023" Increment="1" Value="100"/>
<ComboBox Name="SizeS" SelectedIndex="0">
    <ComboBoxItem>GB</ComboBoxItem>
    <ComboBoxItem>TB</ComboBoxItem>
</ComboBox>

I am setting the Dialog's DataContext to itself. I have defined the Capacity property:

public ulong Capacity { get; set; }

public CustomWindow()
{
    InitializeComponent();
    DataContext = this;
}

I have already created an IMultiValueConverter, PowerConverter, that takes an int and a string and returns ulong. I think the correct MultiBinding is:

<Window.Resources>
    <local:PowerConverter x:Key="CapacityConverter" />
</Window.Resources>

<MultiBinding Converter="{StaticResource CapacityConverter}">
    <Binding ElementName="SizeN" Path="Value" />
    <Binding ElementName="SizeS" Path="SelectedValue" />
</MultiBinding>

I can't figure out how to assign this binding to the Capacity property on the Dialog. I want WPF to automagically set the Capacity property for me. Any ideas?


Solution

  • I had to convert Capacity into a DependencyProperty on CustomWindow, set the SelectedValuePath attribute on the ComboBox, and assign the binding to Capacity in the style.

    XAML:

    <Window xmlns:="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:xctk="clr-namespace:Xceed.Wpf.Toolkit;assembly=WPFToolkit.Extended"
            xmlns:local="clr-namespace:MyProject"
            x:Class="MyProject.CustomWindow" Title="CustomWindow"
            DataContext="{Binding RelativeSource={RelativeSource Self}}">
        <Window.Resources>
            <local:PowerConverter x:Key="CapacityConverter" />
        </Window.Resources>
        <Window.Style>
            <Style TargetType="{x:Type local:CustomWindow}">
                <Setter Property="Capacity">
                    <Setter.Value>
                        <MultiBinding Converter="{StaticResource CapacityConverter}"
                                      Mode="TwoWay">
                            <Binding  ElementName="SizeNumber" Path="Value"
                                      Mode="TwoWay" />
                            <Binding  ElementName="SizeSuffix" Path="SelectedValue"
                                      Mode="TwoWay" />
                        </MultiBinding>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Style>
        <StackPanel>
            <xctk:IntegerUpDown Name="SizeNumber" Minimum="1" Maximum="1023" Increment="1"
                                Value="100"/>                        
            <ComboBox Name="SizeSuffix" SelectedIndex="0" SelectedValuePath="Content">
                <ComboBoxItem>GB</ComboBoxItem>                        
                <ComboBoxItem>TB</ComboBoxItem>                        
            </ComboBox>
        </StackPanel>
    </Window>
    

    Code behind:

    public partial class CustomWindow : Window
    {
        public CustomWindow()
        {
            InitializeComponent();
        }
    
        public static readonly DependencyProperty CapacityProperty =
            DependencyProperty.Register("Capacity", typeof(ulong), typeof(CustomWindow));
    
        public ulong Capacity
        {
            get
            {
                return (ulong)GetValue(CapacityProperty);
            }
            set
            {
                SetValue(CapacityProperty, value);
            }
        }
    }