Relay Commands Command Parameter - wpf

I am trying to work with the MVVM principles within a small WPF project using C#.
I have a ListBox that is populated with CheckBoxes created through binding back to the ViewModel. I also have a command bound to the CheckBoxes and wish to pass the CheckBoxes Content as a CommandParameter. I was looking for something like this:
<Binding ElementName="" Path="Content"/>
Unfortunately, because the CheckBoxes are created through a binding I don’t have the element name.
The code for ListBox / ListBoxItem Style is this:
<Style x:Key="CheckBoxListStyle" TargetType="{x:Type ListBox}">
<Setter Property="SelectionMode" Value="Multiple"></Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<CheckBox Command="{Binding SelectedItemCommand, Mode=OneWay, Source={StaticResource comd}}">
<CheckBox.CommandParameter>
<MultiBinding Converter="{StaticResource cv}">
<Binding ElementName="" Path="Content"/>
<Binding ElementName="" Path="IsChecked"/>
</MultiBinding>
</CheckBox.CommandParameter>
<ContentPresenter></ContentPresenter>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
And its implementation is:
<ListBox Grid.Row="1" Style="{StaticResource CheckBoxListStyle}" Name="lstProducts" ItemsSource="{Binding stampInfo, Mode=OneWay, Source={StaticResource vmStamp}}"
DisplayMemberPath="Country" >
</ListBox>
Ultimately my goal is to be able to display the text Contents (Countries in this case) of all the selected items in a text box were each country is separated by a comma. The only thing I am currently missing is the Country.

Do not create a ControlTemplate for ListBoxItem when you really want to display your data items differently, use a DataTemplate instead, that is exactly its purpose. See Data Templating Overview.
Remove the DisplayMemberPath from the ListBox, as you cannot use both use a path and a custom DataTemplate at the same time. You would only set this path, if there was no DataTemplate, but you wanted to specify a concrete property or property path to display.
<ListBox Grid.Row="1"
Style="{StaticResource CheckBoxListStyle}" Name="lstProducts"
ItemsSource="{Binding stampInfo, Mode=OneWay, Source={StaticResource vmStamp}}"/>
Replace the ControlTemplate with a DataTemplate as ItemTemplate. Then bind the Content and CommandParameter to the property Country. The data context is automatically set to the corresponding item in the bound collection of data items. The IsChecked property can be bound using a RelativeSource, which is the CheckBox itself.
<Style x:Key="CheckBoxListStyle" TargetType="{x:Type ListBox}">
<Setter Property="SelectionMode" Value="Multiple"></Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox Content="{Binding Country}"
Command="{Binding SelectedItemCommand, Mode=OneWay, Source={StaticResource comd}}">
<CheckBox.CommandParameter>
<MultiBinding Converter="{StaticResource cv}">
<Binding Path="Country"/>
<Binding Path="IsChecked" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</CheckBox.CommandParameter>
</CheckBox>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
A different option would be to create data items with a property that can be bound to the IsChecked property of CheckBox. Then you could act in the setter of the data item or on e.g. a button click that executes a command, which filters the bound collection in your view model for checked items.

Related

WPF binding path in styling based on parent type

I'm trying to set up automation id's on all elements of type ComboBoxItem inside Style element. I'm using Binding Path as a source for automation id property.
The problem is that the Path value should be different depends on the parent of ComboBoxItem. Sometimes it's regular ComboBox and sometimes it's our own custom ComboBox. In the former case the Path value is Content and in the latter case the Path value is Text.
<UserControl.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="AutomationProperties.AutomationId">
<Setter.Value>
<Binding Path="Text" /> or <Binding Path="Content"
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
How to set up that condition in XAML?
Thanks in advance
You can try PriorityBinding:
<UserControl.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="AutomationProperties.AutomationId">
<Setter.Value>
<PriorityBinding>
<Binding Path="Text" />
<Binding Path="Content" />
</PriorityBinding>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>

How can I binding a listboxitem content in a muiltbinding?

I am doing my first project using wpf. I really need your help and suggestion. Thanks in advance.
I am building a screen, which has two listboxes A & B. Listbox A is binding to items load from database. listbox B is binding to a statics list. When user selects an item in listbox A, the associate item will be highlighted in listbox B. I am doing it by using MultiBinding in a listboxtitem. I'd like to pass selected data object and listboxitem content. The Convert() will take these two variables and check them. If match, it will return true to IsSelected property of item and highlight it. But it seems item content (statics string) can't be passed to converter(). What should I do?
see my xaml code:
<ListBox Name="AbsenseCode" ItemsSource="{Binding absenseCodeItems}" Grid.Row="1" Grid.Column="1" Grid.RowSpan="5" Margin="20,0,20,5" >
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected">
<Setter.Value>
<MultiBinding Converter="{StaticResource IsItemSelected}">
<Binding ElementName="FilterListbox" Path="SelectedItem"/>
<Binding Path="Content"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
when debugging, the second binging variable, content of item, is "{DependencyProperty.UnsetValue}".
this is a few months old, but I had a similar situation.
First, build a iMultiValueConveter that will compare two values and return the result to a string. "true" or "false" or "yes" or "no".
then in the XAML, define a style that can be triggered by the converter return. In this, ListBoxB has an ellipse where the fill will be green if the values match, red if they dont:
<Window.Resources>
<myNamespace:IsEqualConverter x:Key="IsEqualConverter" />
</Window.Resources>
<ListBox Name="ListBoxA" ItemsSource="{Binding}">
</ListBox>
<ListBox Name="ListBoxB" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<StackPanel>
<StackPanel.Resources>
<!-- style triggered by converter result -->
<Style TargetType="Ellipse" x:Key="EllipseStyle">
<Setter Property="Fill" Value="#E5E5E5" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=result,Path=Text}" Value="true">
<Setter Property="Fill" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=result,Path=Text}" Value="false">
<Setter Property="Fill" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Ellipse Height="50" Width="50" Style="{StaticResoure EllipseStyle}" />
<TextBlock x:Name="value0" Text="{Binding ElementName=ListBoxA,Path=SelectedItem.(Whatever),Mode=OneWay}" />
<TextBlock x:Name="value1" Text="{Data Binding you want to compare to}" VerticalAlignment="Center" HorizontalAlignment="Left" />
<TextBlock x:Name="result">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource IsEqualConverter}">
<Binding ElementName="value0" Path="Text" />
<Binding ElementName="value1" Path="Text" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
</ListBox.ItemTemplate>
</ListBox>

XamDataGrid CellValuPresenter tooltip style

I am trying to create a style for my XamDataGrid so that I can determine what values to show in a tooltip based on the current cell that is being hovered over.
I am trying the below:
<Style x:Key="MyCVPStyle" TargetType="{x:Type igDP:CellValuePresenter}">
<Setter Property="ToolTip">
<Setter.Value>
<StackPanel>
<ListView ItemsSource="{Binding RelativeSource={...}, Path=Field, Converter={StaticResource MyFieldConverter}}">
...
The DataContext of the style is set to the DataRecord. The problem I am having is that I do not know how to access the actual field of the cell value presenter.
I tried setting the source to:
{Binding RelativeSource={RelativeSource AncestorType={x:Type igDP:CellValuePresenter}}, Path=Field
but that fails with a binding error:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='Infragistics.Windows.DataPresenter.CellValuePresenter', AncestorLevel='1''. BindingExpression:Path=Field; DataItem=null; target element is 'ListView' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
How can I access/bind to the CellValuePresenter.Field so I can pass that value to my converter?
As a reference, I have other CellValuePresenter styles that work without issue where I access the Field. For example, here the second binding param is the Field, accessed by referencing Self:
<Setter Property="BorderThickness">
<Setter.Value>
<MultiBinding Converter="{StaticResource BorderThicknessConverter}">
<MultiBinding.Bindings>
<Binding Path="DataItem" />
<Binding RelativeSource="{RelativeSource Self}" Path="Field" />
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
You could use the PlacementTarget property of ToolTip, which will be the CellValuePresenter, and set it as the DataContext that the ListView is binding to:
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget}">
<StackPanel>
<ListView ItemsSource="{Binding Path=Field, Converter={StaticResource MyFieldConverter}}"></ListView>
</StackPanel>
</ToolTip>
</Setter.Value>
</Setter>
I found an alternate solution that I feel is more straight forward.
Create the following style (I believe the property you are trying to bind ItemsSource to is named Field)
<Style x:Key="MyCVPStyle" TargetType="{x:Type igDP:CellValuePresenter}">
<Setter Property="ToolTip">
<Setter.Value>
<StackPanel>
<ListView ItemsSource="{Binding Path=Cells[Field].Value}" />
</StackPanel>
</Setter.Value>
</Setter>
</Style>
But this does require that you have the field you're binding your ItemsSource to defined in FieldLayout.Fields. You may want to set the Visibility of that field to collapsed. I've also included the field that has the tooltip style applied to it.
<igDP:Field Label="Value" Name="Value" >
<igDP:Field.Settings>
<igDP:FieldSettings CellValuePresenterStyle="{StaticResource ResourceKey=MyCVPStyle}" />
</igDP:Field.Settings>
</igDP:Field>
<igDP:Field Label="Field" Name="Field" Visibility="Collapsed" />
You could use a different style for the different fields within the XamDataGrid so that each style would already be set up for the specific field.
The reason why the binding is failing is because the tooltip is shown in a pop up so it is another window and not in the same visual tree as the CellValuePresenter.

Multibound ToolTips per ListView row

I want the information from cells of multiple columns displayed in a tooltip (also some calculation is needed).
This code only shows how to make a tooltip for each row of the listbox, what do I need to change?
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ToolTip" Value="{Binding Path=Name}" />
</Style>
</ListView.ItemContainerStyle>
<!--alle the columns and stuff-->
</ListView>
You could bind using a MultiValueConverter and pass the columns you want.
Or you could add an extra property to each row that provides the calculated value and bind to that.
EDIT
<Setter Property="ToolTip">
<Setter.Value>
<MultiBinding Converter="{local:ThingsToTooltipConverter}" Mode="OneWay">
<Binding Path="Column1"/>
<Binding Path="Column2" />
<Binding Path="Column3" />
</MultiBinding>
</Setter.Value>
</Setter>

Devexpress DXGrid - printing/exporting a custom cell style

I am a newby in DE controls and I am still evaluating the product and I have a litle problem.
I have a grid that has two columns which backcolors is defined by a record status(for example if the status is 1,cell's backcolor must be red). For collumn's CellStyle I am using my custom customCellStyle and Everything work fine.
<Style x:Key="customCellStyle" BasedOn="{StaticResource {dxgt:GridRowThemeKey ResourceKey=CellStyle}}" TargetType="{x:Type dxg:CellContentPresenter}">
<Setter Property="Background">
<Setter.Value>
<MultiBinding>
<MultiBinding.Converter>
<local:StatusToBackroundColorConverter />
</MultiBinding.Converter>
<Binding Path="Column" RelativeSource="{RelativeSource Self}" />
<Binding Path="Data.RowHandle.Value" />
<Binding Path="Data.DocumentStatusId" />
</MultiBinding>
</Setter.Value>
</Setter>
But, when I try to accomplish for exporting or printing grid view, it simply does not work. Although, it works if the cell's back color is hardcode, I cannot make it to work with the binding . The code looks like:
For the sake of the simplicity here I am not using the converter; StatusBackColor has a type of Brush.
<Style x:Key="customPrintCellStyle" BasedOn="{StaticResource {dxgt:TableViewThemeKey ResourceKey=DefaultPrintCellStyle}}" TargetType="dxe:TextEdit">
<Style.Setters>
<Setter Property="dxp:ExportSettings.TargetType" Value="Panel"/>
<Setter Property="DisplayTemplate">
<Setter.Value>
<ControlTemplate TargetType="dxe:TextEdit">
<dxe:TextEdit Text="{Binding Value}"
TextWrapping="Wrap"
IsPrintingMode="True"
Margin="4"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Left"
dxp:ExportSettings.Background ="{Binding Path=StatusBackColor}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
With the static(dxp:ExportSettings.Background ="red") color it works.
Any idea? Please help, I am stuck :)
KR, Sebastjan
I know this is old but in case someone gets here as I did - you probably need to modify your binding expression to access the row's data. For the PrintCellStyle you do this via RowData.Data, so your expression becomes
dxp:ExportSettings.Background ="{Binding Path=RowData.Row.StatusBackColor}"
You need a Color Property, not a Brush Property, to bind on dxp:ExportSettings.Background.

Resources