How do I access ListViewItem? - wpf

The Items collection of a ListView contains the actual business objects. How do I obtain the corresponding ListViewItem given a business object (SelectedItem)?

If you really need to, use the ListView's ItemsContainerGenerator property. However, you can often get away with not setting an ItemContainerStyle with Bindings:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsSpecial}"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
In the above XAML, the ListViewItems will be selected if the underlying bound object's IsSpecial property is true. Selecting/deselecting will update the IsSpecial property.

Related

Binding row selection to ViewModel's property

This should be simple but am stuck with it. If my DataGrid is bound to a collection (say a DataTable) and one of the public properties of the items (DataRows) is named IsHighlighted, can I bind my DataGrid's rows IsSelected status to this property, so that changing the property value in the table would reflect in the UI by selecting/unselecting corresponding DataGrid rows?
Try this
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsHighlighted}"/>
</Style>
</DataGrid.RowStyle>
Above snippet seems to be correct with a slight modification.
Try this
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsHighlighted, Mode="TwoWay"}"/>
</Style>
</DataGrid.RowStyle>
I am assuming you have implemented INotifyPropertyChanged interface in your model class.
Figured this out through Snoop. The DataContext of a DataGridRow (when the DataGrid is bound to a DataTable) is DataRowView and not DataRow. The problem was that IsHighlighted was a public property added thru the DataRow's partial class and therefore didn't make its way to the DataRowView. I have now added an explicit column to the DataTable through the DataSet designer and everything is working fine. Hope it helps someone down the road.

How to change wpf listviewitem background color when its data is using binding?

I'm trying to change listview's row background color for a data binding listview.
From msdn, I know there is ListViewsItem.Backgroud for the color of its background.
But since I'm using data binding for ListView's data source,the type of ListView's item is actually my class type, no longer ListViewItem. So I can't find its Background property.
I guess I missed something, how should I do it?
Thanks
You can set ItemContainerStyle of your listview like below to set any property on item.
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Red"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
You even change the background depending of dataitem state using triggers in style.

Set parent controls property in xaml

I have a panel with a custom ListView. The ListView's items contains a GroupBox. The GroupBox contains a ListView. This ListView's items contains a GroupBox and so on.
All of the controls above have custom templates and styles
There are ToggleButtons in the Controls VisualTree lowest nodes.
When these buttons are checked I need to disable all the panel except of the button was clicked.
I would like to avoid event chaining through the parents in viewModel classes.
I'm using mvvm pattern and I would like to solve it in the xaml side if its possible.
EDIT: Here is a screenshot and the Pick button should disable the panel
Any suggestions are warmly welcomed.
you need to implement the relative source binding something like below.
IsEnabled="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}},Path=IsEnabled}"
Just have a read-only property in your ViewModel that is the negation of the property that your ToggleButton is bound to.
ViewModel:
private Boolean mSourceIsPicked;
public Boolean SourceIsPicked
{
get { return mSourceIsPicked; }
set
{
SetProperty("SourceIsPicked", ref mSourceIsPicked, value);
NotifyPropertyChanged("IsSourceChangeable");
}
}
public Boolean IsSourceChangeable
{
get { return ! this.SourceIsPicked; }
}
Then, in your View, just bind the IsEnabled property of the other controls to that new property.
<ComboBox ItemsSource="{Binding SourceTypes}"
IsEnabled={Binding IsSourceChangeable}" />
The advantage of binding to a property is that you can add/remove controls in your view and just bind to this property without changing additional XAML. You can also change the behavior of any control by not binding to this property.
If you really want a XAML-only solution, you can name each of the controls in the panel, and use a DataTrigger using TargetName on the "SourceIsPicked" property to disable the others:
<ComboBox x:Name="cboSourceTypes" ... />
<ComboBox x:Name="cboSourceNames" ... />
<ToggleButton>
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Style.Triggers>
<DataTrigger Binding="{Binding SourceIsPicked}" Value="True">
<Setter TargetName="cboSourceTypes"
Property="IsEnabled"
Value="False" />
<Setter TargetName="cboSourceNames"
Property="IsEnabled"
Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
Note that this is all freehand, so you may need to adjust it a bit, but it gives you the idea.

How can the ViewModel drive a ControlTemplate?

I have the problem that parts of the TreeView Controltemplate need to change depending on the state of the bound (ItemsSource) ViewModels. For example the little expander icon needs to be exchanged with a different drawing based on each items ViewModel state. Additonally based on the state of each ViewModel the child items need to be arranged horizontally instead of the default vertically.
It sounds like you have to customize ItemsContainerStyle, not ControlTemplate. For example, if you want to mark TreeViewItem as selected whenever underlying ViewModel is selected, you can use the following style:
<TreeView ItemsSource="{Binding ...}
...>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<!-- IsSelected is a property on ViewModel item -->
<Setter Property="IsSelected" Value="{Binding IsSelected}"/>
<Setter .../>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
If Binding doesn't suit you, you can use Converters, Triggers in Style or ControlTemplate. Furthermore, you can also use triggers in DataTemplates.
PS: Wrote the code from head. May have a typo.

wpf checked list box question

I am creating checked list box with the following template:
<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 IsChecked="{Binding Path=xxxxxxxxxxx,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"> <ContentPresenter></ContentPresenter>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
<ListBox Style="{StaticResource CheckBoxListStyle}" ItemsSource="{Binding Path=Configuration.ProductTypes}" DisplayMemberPath="ProductName" />
my problem is, i am getting all the product types from Database and binding it to the list box itemssource. i have a product class which contains a list of product types it belongs to. i need to set the IsChecked property of check boxes based on Product's product type list. Typically i need to set one or more check boxes IsChecked property. product may belong to 1 or more product types. and selection mode is multiselect. if user checks the additional product type check boxes ..i need to get the total checked list boxes and save them to the database... this is a MVVM WPF application ... any ideas on how to solve this scenario...
in the controltemplate what will be the path is IsChecked?
Thanks
Rey
Let me simplyfy my question: I need a list box with checkbox and textblock. textblock data context is different and check box data context is different. i mean they get their data from different objects. no idea how to achieve this...
Let me simplyfy my question: I need a
list box with checkbox and textblock.
textblock data context is different
and check box data context is
different. i mean they get their data
from different objects. no idea how to
achieve this...
Create a new class (a ViewModel) which contains the two data contexts (Model1 and Model2) and data bind to it, also known as the MVVM pattern.
The ProductType class that you're binding to the ListBox should have a read/write property called IsSelected or IsChecked that you can bind to. Then instead of using a ControlTemplate, use a DataTemplate on the ListBox.ItemTemplate and bind the CheckBox's IsChecked property to that property.

Resources