WPF MultiBinding same converter with different binding path - wpf

I have ten UI Controls of the same type in a UI and all will be using same multi binding converter.
The problem is I can not create a common style for multibinding which I can apply to all UI controls to avoid duplicate code, as each control will use a different binding property to pass as a Binding to converter.
Is there any way in WPF we can avoid duplicate code for this scenario?

You can extend MarkupExtension, which allows you to define a custom Converter wrapper and then just call it with the 2 Paths.
Edit: in your case it's probably best to inherit directly from MultiBinding and set sensible defaults in the constructor.

I assume you have something like this:
<Button>
<Button.Content>
<MultiBinding Converter="{StaticResource conv}">
<Binding Path="COMMON" />
<Binding Path="SPECIFIC1" />
</MultiBinding>
</Button.Content>
</Button>
<Button>
<Button.Content>
<MultiBinding Converter="{StaticResource conv}">
<Binding Path="COMMON" />
<Binding Path="SPECIFIC2" />
</MultiBinding>
</Button.Content>
</Button>
<Button>
<Button.Content>
<MultiBinding Converter="{StaticResource conv}">
<Binding Path="COMMON" />
<Binding Path="SPECIFIC3" />
</MultiBinding>
</Button.Content>
</Button>
and so on...
this looks ugly, I agree.
I am not aware of any alternatives, however by thinking a little, you could create(imo) a little better solution:
just create new CommonMultiBindings.xaml;
which includes:
<MultiBinding Converter="{StaticResource conv}">
</MultiBinding>
and voila, done. Now just reference it as CommonMultiBindings object and use it as:
<Button.Content>
<CommonMultiBindings>
<!--Actual bindings here-->
</CommonMultiBindings>
</Button.Content>
you can take it further by factoring "" into the CommonMultiBindings and adding new property(UserBindings) which will be used to synchronize between Bindings property.
Ideally, you would want to create a custom MultiBinding class which has style property. Then you could do something like this + combined with "custom" default bindings which are automatically added to "Bindings" collection
<Grid.Resources>
<Style TargetType="MultiBinding">
<Setter Property="Converter" Value="{StaticResource conv}" />
</Style>
</Grid.Resources>

Related

Wpf Multibinding in a template or style

I have a class with many properties (not in a list) which must be switchable in view. The converter itself works fine using multibinding.
<TextBox Grid.Row="1" Grid.Column="5">
<TextBox.Text>
<MultiBinding Converter="{StaticResource IntValueConvertor}">
<Binding Path="property1" />
<Binding Path="IntegerDisplay" />
</MultiBinding>
</TextBox.Text>
</TextBox>
In the code, "IntegerDisplay" is a property which is defined in my VM.
Property1 is one of the many properties which must be viewed differently (depending on IntegerDisplay).
What I want to avoid is the need of adding the whole multibinding convertor to each textbox.
Something in this style:
<TextBox
Grid.Row="1"
Grid.Column="4"
Text="{Binding Path=Property1, Converter={StaticResource IntValueConvertor}}" />
I know this code does not work!
I tried using a style, but I could not get to the value of property1.
Is it the best way to use a style or is a datatemplate better?
Kind regards
I recommend sticking with a style and here's a basic start to doing so.
<!--This will go in your resources-->
<Style x:Name="TextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Text" Value="{Binding Path=Property1, Converter={StaticResource IntValueConverter}, ConverterParameter=IntegerDisplay}"/>
</Style>
<!--This will go in your Display-->
<TextBox Style="{StaticResource TextBoxStyle}"/>

Bind a property to an existing Binding

I have an interface with multiple buttons. I'd like to enable or disable these buttons according to a 'complex' condition. I declared this MultiBinding as an application resource in order to avoid code repetition:
<MultiBinding x:Key="MyMultiBinding" Converter="{StaticResource ResourceKey=MyConverter}">
<Binding Path="IsConnected" />
<Binding Path="IsOpened" />
</MultiBinding>
Here is how I declare my button:
<Button Name="MyButton" Content="Click me!" IsEnabled="{StaticResource ResourceKey=MyMultiBinding}" />
At runtime, I get the following error: "Set property IsEnabled threw an exception... MultiBinding is not a valid value for property IsEnabled".
I can't figure why this is not working. Could you please point me to the right way to do this? Thank you.
You can't set the boolean IsEnabled property to a value of type MultiBinding. That is what is happening.
As #Viv pointed out, you could declare a Style to do the heavy lifting:
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{StaticResource ResourceKey=MyConverter}">
<Binding Path="IsConnected" />
<Binding Path="IsOpened" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
<Button Name="MyButton" Content="Click me!" Style="{StaticResource ButtonStyle}" />
This works well if the Button DataContext has those properties. It works especially well if they each have a different DataContext they are bound to, enabling them for different reasons.
If they are all bound to the same DataContext, or the properties are on a different object, you could use the Freezable Trick to provide a value that your buttons would bind to:
<BindingProxy x:Key="isEnabled">
<BindingProxy.Data>
<MultiBinding Converter="{StaticResource ResourceKey=MyConverter}">
<Binding Path="IsConnected" />
<Binding Path="IsOpened" />
</MultiBinding>
</BindingProxy.Data>
</BindingProxy>
<Button Name="MyButton" Content="Click me!" IsEnabled="{Binding Data, Source={StaticResource isEnabled}}" />
I don't know if this is the best solution, but wrapping the MultiBinding into a style, as Viv said, did the trick. Here is the code of the Style :
<Style x:Key="MyStyle" TargetType="Button">
<Style.Setters>
<Setter Property="IsEnabled">
<Setter.Value>
<MultiBinding Converter="{StaticResource ResourceKey=MyConverter}">
<Binding Path="IsConnected" />
<Binding Path="IsDataAccessOpened" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
And the code of the button :
<Button Name="MyButton" Content="Click me!" Style={StaticResource ResourceKey=MyStyle} />

text box with multiple bindings?

Is there a way have a single textbox bind to two things. I want to have one binding set to "OneWay" and the Other set to "OneWayToSource". Basically I want to combine these two textboxes into one (and preferably with little to no code behind).
<TextBox Text="{Binding Path=ActionParameter.Value, Mode=OneWayToSource}" />
<TextBox Text="{Binding Path=StatusSignal.Value, Mode=OneWay}" />
You can use MultiBinding to set 2 or more bindings to your TextBox
Example:
<TextBox>
<TextBox.Text>
<MultiBinding StringFormat="{}{0}{1}">
<Binding Path="ActionParameter.Value" Mode="OneWayToSource" />
<Binding Path="StatusSignal.Value" Mode="OneWay" />
</MultiBinding>
</TextBox.Text>
</TextBox>
But depending on what you need to do with the 2 properties you may need to use a IMultiValueConverter to process the properties.
Example:
<TextBox>
<TextBox.Resources>
<local:TextConverter x:Key="MyConverter"/>
</TextBox.Resources>
<TextBox.Text>
<MultiBinding Converter="{StaticResource MyConverter}">
<Binding Path="ActionParameter.Value" Mode="OneWayToSource" />
<Binding Path="StatusSignal.Value" Mode="OneWay" />
</MultiBinding>
</TextBox.Text>
</TextBox>

WPF XamComboBox DisplayMemberPath with concatenated values

I have the following code -
<igEditors:XamComboEditor ItemsSource="{Binding Instances}"
Margin="5,2,5,2" Width="175" HorizontalAlignment="Left"
SelectedItem="{Binding SelectedInstance,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnDataErrors=True,ValidatesOnExceptions=True}"
>
<igEditors:XamComboEditor.ComboBoxStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="Name" />
<Binding Path="Id" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</igEditors:XamComboEditor.ComboBoxStyle>
</igEditors:XamComboEditor>
When I set the SelectedInstance from my viewmodel, the combobox is displaying the type of the object. If I then make a selection, it displays correctly, but I click out of the combobox, losing focus, it reverts back to the object type. If I set the DisplayMemberPath manually to just Name, it works correctly, but I really need it to be a concatenated value for the displaymemberpath.
Can anyone help?
Thanks
The answer to this question was to use the ValueToDisplayTextConverter along with a custom converter. More details can be found here -
http://www.infragistics.com/community/forums/p/77378/390782.aspx

How can I pass a constant value for 1 binding in multi-binding?

I have a multi-binding like
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myConverter}">
<Binding Path="myFirst.Value" />
<Binding Path="mySecond.Value" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
And I want to pass a fixed value e.g. "123" to one of the two bindings above. How can I do that using XAML?
If your value is simply a string, you can specify it as a constant in the Source property of a binding. If it is any other primitive data type, you need to define a static resource and reference this.
Define the sys namespace in the root of the XAML to point to System in mscorlib, and the following should work:
<TextBlock>
<TextBlock.Resources>
<sys:Int32 x:Key="fixedValue">123</sys:Int32>
</TextBlock.Resources>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myConverter}">
<Binding Path="myFirst.Value" />
<Binding Source="{StaticResource fixedValue}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
Or, combining the two answers above:
Define the namespace sys at the document head:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
and then:
<MultiBinding Converter="{StaticResource ScalingConverter}">
<Binding>
<Binding.Source>
<sys:Double>0.5</sys:Double>
</Binding.Source>
</Binding>
<Binding ElementName="TC" Path="ActualWidth" />
</MultiBinding>
Which provides the right type without the Resources kludge.
I don't quite follow the question but there are two options:
Put the line <Binding Source="123" /> in your multibinding will pass 123 as a bound value to your converter.
Put ConverterParameter="123" in your MultiBinding:
<MultiBinding Converter="{StaticResource conv}" ConverterParameter="123">
I'm not saying this an especially good answer but here is another approach:
<Binding Path="DoesNotExist" FallbackValue="123" />

Resources