I'm trying to use multibinding on a context menu stored in Window.Resources and I can't figure out how to get the SelectedItem of the ListBox I attach the menu to.
I think I need to use PlacementTarget, but can't get anything to work. I tried using FindAncestor, but that didn't work. I also tried getting the listbox by the ElementName to no avail.
<Window ...>
<Window.DataContext>
<local:IPViewModel/>
</Window.DataContext>
<Window.Resources>
<sys:Int32 x:Key="Number">0</sys:Int32>
<sys:Int32 x:Key="NumberLetter">1</sys:Int32>
<sys:Int32 x:Key="NumberLetterNumber">2</sys:Int32>
<local:CombineParams x:Key="CombineParams"/>
<ContextMenu x:Key="DetailMenu">
<MenuItem Header = "Number">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding SwitchLabelMode}">
<i:InvokeCommandAction.CommandParameter>
<MultiBinding Converter="{StaticResource CombineParams}">
<!-- The next line is where I'm not sure what to write to get to the listbox -->
<Binding Source="{RelativeSource AncestorType={x:Type ListBox}}"/>
<Binding Source="{StaticResource Number}"/>
</MultiBinding>
</i:InvokeCommandAction.CommandParameter>
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
...
</Window.Resources>
...
<ListBox Name="IndexDetailsListBox"
...
ContextMenu="{StaticResource DetailMenu}"
...>
</ListBox>
...
</Window>
I can't get it to give back anything other than unset value.
I'm grateful for any help. None of the other questions I found have the contextmenu in Window.Resources with MultiBinding which seems to be my issue.
Your problem is, that you assign RelativeSource- object to the Source property of the Binding object. RelativeSource- object belongs to the RelativeSource-property.
So you get your List to the multi value converter:
<MultiBinding Converter="{StaticResource CombineParams}">
<Binding Path="PlacementTarget" RelativeSource="{RelativeSource AncestorType={x:Type ContextMenu}}"/>
<Binding Source="{StaticResource Number}"/>
</MultiBinding>
Related
I've been trying to implement a dynamic ToolTip (WPF) for RadioButton (the ToolTip switches, when IsEnabled of the RadioButton changes). I wanted to achieve this with a MultiValueConverter, which would be sort of a general Converter, that accepts 3 values - the IsEnabled value, enabled ToolTip and disabled ToolTip in this exact order.
But sadly I have encountered an issue, that I haven't been able to solve yet. Basically when the code reaches the Convert Method, the Array of values is filled with DependencyProperty.UnsetValue items.
What I managed to find while googling was, that the problem is propably caused by having a wrong DataContext as mentioned here WPF MultiBinding in Convertor fails ==> DependencyProperty.UnsetValue , but I feel like I have tried every combination of RelativeSources and DataContexts, that I could come up with and nothing helped.
Here is the sample code of the View:
<window.Resources>
<local:BooleanToStringConverter x:Key="BooleanToStringConverter"/>
</window.Resources>
<Grid>
<RadioButton x:Name="RadioButton" ToolTipService.ShowOnDisabled="True"
IsEnabled="{Binding IsRadioButtonEnabled}" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Radio">
<RadioButton.ToolTip>
<ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource BooleanToStringConverter}">
<Binding ElementName="RadioButton" Path="IsEnabled"/>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type local:MainWindow}}" Path="ViewModel.EnabledToolTip"/>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type local:MainWindow}}" Path="ViewModel.DisabledToolTip"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
</RadioButton>
So the result, that I expect from this, is that the correct values will be passed into the Converter (in this case value of IsEnabled and string values of Enabled/Disabled ToolTips).
If anybody has any ideas, I would very much appreciate to hear them :).
Thanks in advance.
I managed to fix this by explicitly setting DataContext on the RadioButton and removing the RelativeSources within the MultiBinding. Though I don't understand why it did not work with the RelativeSources, it works. Here is the code, in case of anyone reading this in the future:
<RadioButton x:Name="RadioButton" ToolTipService.ShowOnDisabled="True"
DataContext="{Binding ViewModel, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"
IsEnabled="{Binding IsRadioButtonEnabled}" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Radio">
<RadioButton.ToolTip>
<ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource BooleanToStringConverter}">
<Binding Path="IsRadioButtonEnabled"/>
<Binding Path="EnabledToolTip"/>
<Binding Path="DisabledToolTip"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ToolTip>
</RadioButton.ToolTip>
</RadioButton>
I have a rookie question, but I couldn't find an answer for that. I'm not even sure how to ask google that question.
Let's say you have:
Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}, AncestorLevel=2}}"
How to do it this way?:
<Button.Tag>
<Binding ??? RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type StackPanel}, AncestorLevel=2}" />
</Button.Tag>
I've tried "Content" "Value" "Source".. Thanks for help!
<Button ...>
<Button.Tag>
<Binding .../>
</Button.Tag>
</Button>
is equivalent to
<Button Tag="{Binding ...}" />
However, you are missing the Binding's source property path. Add Path="DataContext":
<Button.Tag>
<Binding Path="DataContext" .../>
</Button.Tag>
How to pass two parameters from XAML, one Type object and one Model {Binding}, to ViewModel as CommandParameter. I came across different posts on SO but all are using control bindings. Is there any way to pass Type instead.
I want something like this:
<MenuItem x:Key="RuleBase" Header="RuleBase" x:Shared="False"
Command="{Binding DataContext.AddRuleCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
<MenuItem.CommandParameter>
<MultiBinding Converter="{StaticResource MultiParameterConverter}">
<Binding Path="{Binding}" />
<Binding Path="{x:Type local:RuleBase}" />
</MultiBinding>
</MenuItem.CommandParameter>
</MenuItem>
This piece of code is working with one parameter alone:
<MenuItem x:Key="RuleBase" Header="RuleBase" x:Shared="False"
Command="{Binding DataContext.AddRuleCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{x:Type local:RuleBase}" />
you can use this binding in the multibinding:
<MultiBinding Converter="{StaticResource MultiParameterConverter}">
<Binding />
<Binding Source="{x:Type local:RuleBase}" />
</MultiBinding>
but since the Type won't change and there is only one true binding in the multibinding expression, it could be rewriten like this:
<MenuItem CommandParameter="{Binding ConverterParameter={x:Type local:RuleBase},
Converter={StaticResource YourConverter}}" />
Try to pass a whole MenuItem as a command parameter:
CommandParameter="{Binding RelativeSource={RelativeSource Self}}"
you must use an ICommand implementation that can take a parameter.
I just started to programm in C# and got the following error message "A 'MultiBinding' cannot be used within a 'SetterBaseCollection' collection. A 'MultiBinding' can only be set on a DependencyProperty of a DependencyObject". My dea was to disable some of the combobox depedant of the input values given to the converter. use the same converter later in the xaml file and have no error..
<DataTemplate x:Key="ComboBoxDirectionCellDataTemplate">
<Canvas>
<ComboBox Name="DirectionBi" ItemsSource="{Binding Source={StaticResource DirectionBiList}}" SelectedItem="{Binding Direction, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="#FFCDCDCD" />
<ComboBox Name="DirectionOut" ItemsSource="{Binding Source={StaticResource DirectionOutList}}" SelectedItem="{Binding PinFunctionOptions[SelectedPinFunctionIdx].SupportedDirections, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="#FFCDCDCD" />
<ComboBox Name="DirectionIn" ItemsSource="{Binding Source={StaticResource DirectionOutList}}" SelectedItem="{Binding PinFunctionOptions[SelectedPinFunctionIdx].SupportedDirections, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Background="#FFCDCDCD" />
</Canvas>
<DataTemplate.Triggers>
<DataTrigger Value="In">
<MultiBinding Converter="{StaticResource FunctionToGroupConverter}">
<Binding Path="PinFunctionOptions"/>
<Binding Path="SelectedPinFunctionIdx"/>
</MultiBinding>
<Setter TargetName="DirectionBi" Property="Visibility" Value="Hidden"/>
Thanks for help!!!!
I may be wrong - and i have no way of checking this at the moment...
I think what you want is the following...
<DataTrigger ...>
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource FunctionToGroupConverter}">
<Binding Path="PinFunctionOptions"/>
<Binding Path="SelectedPinFunctionIdx"/>
</MultiBinding>
</DataTrigger.Binding>
</DataTrigger>
DataTemplate.Triggers is expecting a collection of Setter why are you attempting to put a MultiBinding in there?
The exception you're getting is a result of this.
I'm not entirely certain what you're attempting with the MultiBinding but you may fare better by performing the bindings individually on the respective elements.
I'm trying to create drag adorner based on whether the Customer DependancyProperty of a Window is null. I have this in the Window's resources. The first part of the binding is set (the item being dragged), but the second (the DependancyProperty on the WIndow) shows as UnsetValue.
The property is definitely initialized as it's used as the window's datacontext.
<Window x:Name="root"
...
>
<Window.Resources>
<DataTemplate x:Key="DragAdorner">
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource vehicleDragConverter}">
<Binding/>
<Binding Path="Customer" ElementName="root"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
customer is not a direct property of element window.
use <Binding Path="DataContext.Customer"..../>
or you can also use RelativeSource=FindControl Window in binding.