Binding row selection to ViewModel's property - wpf

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.

Related

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.

Binding a WPF Style Trigger to a custom dependency property

I have found numerous similar threads here, but none that seem to address my specific issue.
I need to highlight the background of a textbox under certain conditions. I have created a Highlight property and tried using a trigger in a style to set it but it doesn't actually ever highlight the text.
Here is my Style, simplified:
<Style x:Key="TextBoxStyle" BasedOn="{StaticResource CommonStyles}">
<Style.Triggers>
<Trigger Property="Elements:DataElement.Highlight" Value="True">
<Setter Property="Control.Background"
Value="{DynamicResource EntryBoxHighlightBackground}"/>
</Trigger>
</Style.Triggers>
</Style>
Elements is defined as:
xmlns:Elements="clr-namespace:MDTCommon.Controls.Forms.Elements">
Then I have the section where the style is applied:
<!-- Applies above style to all TextBoxes -->
<Style TargetType="TextBox" BasedOn="{StaticResource TextBoxContentHolder}" >
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<!-- Overrides the default Error Style -->
</Style>
In the code behind of the DataElement class is the following:
public static readonly DependencyProperty HighlightProperty =
DependencyProperty.Register("Highlight", typeof(bool), typeof(DataElement));
public bool Highlight
{
get { return (bool)base.GetValue(HighlightProperty); }
set { base.SetValue(HighlightProperty, value); }
}
A DataElement ultimately derived from UserControl and it contains a reference to TextBox object as well as othe objects.
In the CustomForm class that houses all of the DataElement objects I have the following to set the color.
Resources["EntryBoxHighlightBackground"] = Brushes.Yellow;
So, the first issue is that setting the Highlight property for the DataElement doesn't cause the textbox background to draw in yellow.
The other issue is that I realize that I am applying this style to all textboxes and I could have textboxes in other areas that are not actually contained within a DataElement, which may cause a binding issue.
Try converting your trigger to a DataTrigger, and add a binding that will look directly at the DataElement control, like so:
<DataTrigger Binding="{Binding Path=Highlight, RelativeSource={RelativeSource AncestorType={x:Type Elements:DataElement}}}" Value="True">
<Setter Property="Control.Background" Value="{DynamicResource EntryBoxHighlightBackground}"/>
</DataTrigger>

ComboBoxItem, IsEnabled, Binding to table value

I have a dropdownlist control and its ItemsSource is a collection of items which of type T_LookupTable, which is a table in the db, and one of it's columns is 'isEnabled'.
How do I bind the IsEnabled property of the ComboBoxItem in the XAML to this value in the collection?
Further, I have numerous drop-downs in the application which employ this same method, so I would like to somehow make this a global feature if possible, through a static resource, is something like that possible? I found this piece of XAML, which will work, but I want the items to be greyed out in the drop-down, and this method only disables them where you can't click them, but there is no visual indicator which says the item is disabled:
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<ContentPresenter x:Name="ContentPresenter" IsHitTestVisible="{Binding Path=isEnabled}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>
I had similar problem with TreeViewItems...
Basically, you have to inherit ComboBox class, override GetContainerForItemOverride method like this:
protected override DependencyObject GetContainerForItemOverride()
{
var result = new ComboBoxItem();
result.SetBinding(Control.IsEnabledProperty, new Binding("IsEnabled"));
return result;
}
It hard codes data binding to IsEnabled property of your data object.

How do I access ListViewItem?

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.

DataTrigger does not work as expected

I have a ComboBox bound to a ViewModel property called Property.
Property is a TypeDescriptor.
When user changes the value in the ComboBox, the Property is updated.
On the UI i would like to either hide or make visible different controls: textbox, combobox, date picker etc.
Problem is, the DataTrigger is not working as expected.
<Style x:Key="textboxStyle"
TargetType="{x:Type TextBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Property.PropertyType}"
Value="{x:Type Type={x:Type sys:String}}">
<Setter Property="Visibility"
Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
You might need to write a Converter which gets invoked when the value of 'Property' changes. The converter can be a 'TypeDescriptior to Visibility converter.
The reason why the above doesnt work is because 'PropertyType' doesnt trigger INotifyPropertyChanged.

Resources