Is it possible to pass the current DataContext as a parameter to a MultiBinding?
<Checkbox.IsEnabled>
<MultiBinding Converter={...}>
<Binding Path="SomeProperty" Mode="TwoWay"/>
<Binding Path="DataContext?" Mode="OneWay"/>
</MultiBinding>
<Checkbox.IsEnabled>
Just use . as Path.
<Binding Path="." Mode="OneWay"/>
Or ignore the Path property alltogether.
<Binding Mode="OneWay"/>
From the Binding.Path documentation:
Optionally, a period (.) path can be used to bind to the current source.
Related
I have two data templates that make use of a multi-binding to control the visibility of a button, e.g. in data template A
<Button.Visibility>
<MultiBinding Converter="{StaticResource HideFirstOrderedItemConverter}" Mode="TwoWay">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" Path="Items"/>
<Binding Path="Entity"/>
</MultiBinding>
</Button.Visibility>
and in data template B
<Button.Visibility>
<MultiBinding Converter="{StaticResource HideFirstOrderedItemConverter}" Mode="TwoWay">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" Path="Items"/>
<Binding Path="Entity"/>
</MultiBinding>
</Button.Visibility>
The data templates are bound to the same list box items source and a data template selector is used to determine which datatemplate to use based on a property of the item in the list (Note: the datatemplate forms part of the ItemTemplate for the ListBox).
Question: Will wpf trigger the MultiBinding converter HideFirstOrderedItemConverter if either the binding to Items or Entity changes, or do both Items and Entity have to change?
Currently my binding on data template A doesn't fire when the Items property changes (an ObservableCollection that has items added and removed) and Entity does not change. Ultimately I would like the binding to fire on both data templates whenever the Items property changes.
If I comment out the binding to Entity in both templates as follows
<Button.Visibility>
<MultiBinding Converter="{StaticResource HideFirstOrderedItemConverter}" Mode="TwoWay">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" Path="Items"/>
<!-- <Binding Path="Entity"/> -->
</MultiBinding>
</Button.Visibility>
My converter gets hit when I add an item to the collection, but only for the data template asscoiated with the item just added. I'd like it to get hit for all items.
UPDATE:
The comments below from #ASh and #GazTheDestroyer helped my understanding here. I need to notify my view of a collection changed event using a property changed event (collection changed events are NOT surfaced to the binding framework). So by updating my XAML to
<Button.Visibility>
<MultiBinding Converter="{StaticResource HideFirstOrderedItemConverter}" Mode="TwoWay">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" Path="DataContext.Entities"/>
<Binding Path="Entity"/>
</MultiBinding>
</Button.Visibility>
where DataContext.Entities is the undelying ObservableCollection, and in the bound view model hook into the collection changed event of that ObservableCollection, i.e.,
Entities.CollectionChanged += CollectionChanged
where the CollectionChanged callback raises the notify property changed event on the Entities ObservableCollection. I believe this is the way to do it (might be nice to abstract this behaviour into its own type).
Will wpf trigger the MultiBinding converter HideFirstOrderedItemConverter if either the binding to Items or Entity changes, or do both Items and Entity have to change?
Either. The problem is that the Items property of the ListBox isn't set when you add or remove items from the source collection. Bind to Items.Count instead:
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}"
Path="Items.Count "/>
This property will change when you add or remove items from the source collection.
Also note that your Entity property must raise the PropertyChanged event for the converter to be re-invoked when you set it.
I want to bind a string value with string format.
I have tried many ways but it didn't work.
Could anybody help me to solve this problem?
This is the way I am currently using, but I still want to use StringFormat.
How could I do this ?
<DiscreteObjectKeyFrame.Value>
<MultiBinding Converter="{StaticResource DotConverter}">
<Binding Path="LoadingStringShow"/>
<Binding>
<Binding.Source>
<sys:Int16>1</sys:Int16>
</Binding.Source>
</Binding>
</MultiBinding>
</DiscreteObjectKeyFrame.Value>
The best way to format a string is to do this in code.
You could use string.Format() or for C#6's new Feature: "Interpolated Strings" as shown below to format your string.
private string _name;
public string Name
{
get {return $"My Name is {_name}";}
set
{
_name = value;
//OnPropertyChanged("Name");
}
}
Your Binding will then show: My Name is <valueofvariable>
Since your bindings name is LoadingStringShow I assume you want to display some kind of loading message.
Maybe this could also help:
<TextBlock Text="{Binding LoadingStringShow, StringFormat={}{0}%}" />
or
<TextBlock TextAlignment="Center">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} - {1}%">
<Binding Path="LoadingStringShow" />
<Binding Path="CurrentValue" />
</MultiBinding>
</TextBlock.Text>
Reference 1
Reference 2
I'm using xaml-Styler Plugin on VS2015. So far I didn't had any problems.
Now I have the problem, that the styler removes linebreaks (I use HTML encoded characters).
xaml (simplified)
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}
Min X: {1:F3}; Max X: {2:F3}">
<Binding Path="Area.Name" ... />
<Binding Path="Area.MinX" ... />
<Binding Path="Area.MaxX" ... />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
after Pressing Save, the xaml styler automatically makes this (html character is removed and LineBreak inserted:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}
Min X: {1:F3}; Max X: {2:F3}">
<Binding Path="Area.Name" ... />
<Binding Path="Area.MinX" ... />
<Binding Path="Area.MaxX" ... />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
then the text is displayed at one line.
I'm not happy with using html encoded characters at all. Is there maybe a better (simple) way to format strings with linebreaks in a MultiBinding?
For this simple formatting I don't want to use a MultiValueConverter, because it is only an informative string...
If I could tell xaml styler don't style this part/line I would be happy, but didn't found the possibility or a property in options of xaml styler.
You can use the hex representation of the LineFeed character (char 10) :
to get a line break :
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}
Min X: {1:F3}
Max X: {2:F3}">
<Binding Path="Area.Name" ... />
<Binding Path="Area.MinX" ... />
<Binding Path="Area.MaxX" ... />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
I have some RadioButton’s that I want to change the Visibility of based on multiple properties in the ViewModel. Each RadioButton’s Visibility will vary based on the same list of properties. I have the following xaml:
<RadioButton Command="{Binding Path=SomeCommand}"
CommandParameter="SomeCommandParameter"
Content="RB 1">
<RadioButton.Visibility>
<MultiBinding Converter="{StaticResource Rb1Visibility}">
<Binding Path="Value1"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Value2"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</RadioButton.Visibility>
</RadioButton>
I would like to change the Converter for each RadioButton option, but everything else would remain the same (all the Bindings). I don’t want to duplicate all the xaml code for this. I originally tried creating a style for the RadioButton, but I could not figure out how to pass the Converter to the Style resource:
<Style x:Key="RbVisibilityStyle"
TargetType="{x:Type RadioButton}">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{???? Pass in converter ?????}">
<Binding Path="Value1"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Value2"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
I could create a “Visibility” property for each RadioButton in the ViewModel, but that adds a lot of code to the ViewModel and addition PropertyChanged event handling.
Is there an easy way to generically bubble up the MultiBinding so I don’t duplicate the code throughout the entire xaml file? Is there a different approach I should be taking?
Update - Adding a more complex example
<RadioButton Command="{Binding Path=SomeCommand}"
CommandParameter="SomeCommandParameter"
Content="RB 1">
<RadioButton.Visibility>
<MultiBinding Converter="{StaticResource Rb1Visibility}">
<Binding Path="Value1"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Value2"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</RadioButton.Visibility>
</RadioButton>
<RadioButton Command="{Binding Path=SomeCommand2}"
CommandParameter="SomeCommandParameter2"
Content="RB 2">
<RadioButton.Visibility>
<MultiBinding Converter="{StaticResource Rb2Visibility}">
<Binding Path="Value1"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Value2"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</RadioButton.Visibility>
</RadioButton>
<RadioButton Command="{Binding Path=SomeCommand3}"
CommandParameter="SomeCommandParameter3"
Content="RB 3">
<RadioButton.Visibility>
<MultiBinding Converter="{StaticResource Rb3Visibility}">
<Binding Path="Value1"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Value2"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</RadioButton.Visibility>
</RadioButton>
How do I reduce the MultiBinding redundancy here?
would like to change the Converter for each RadioButton option,
Create a new MultiValueConverter which takes an extra parameter (the radio button option) and then simply route the call to the appropriate converter based on that option.
One can put the option in the Tag property on the control's Xaml.
Example
Its not clear to me what that option you mention is, so in my example let us uniquely identify each Radio Button by its Tag property and use the routing converter to find the appropriate converter based off of the Tag supplied.
<RadioButton Tag="1"/><RadioButton Tag="2"/>
Then change the style to use the new converter with the new parameter:
<Style x:Key="RbVisibilityStyle"
TargetType="{x:Type RadioButton}">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource RouterViaTagVisibilityConverter">
<Binding Path="Value1"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Value2"
RelativeSource="{RelativeSource Self}" />
<Binding Path="Tag"
RelativeSource="{RelativeSource Self}" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
<MultiBinding Converter="{StaticResource MergeValuesConverter}">
<Binding Path="StructureID" />
<Binding Path="SectionID" />
<Binding Path="ParentStructureID" />
</MultiBinding>
I am only getting the first two bindings.
Is there a way to get the third binding (ParentStructureID)?