listview checkbox binding wpf MVVM - wpf

I am trying to get the bool value of the checkbox present in the Listview. I am binding to a bool public property "Assignm" in the view model. I tried the below binding pattern but the problem is if i select one checkbox it selects all checkboxes and vice versa. I think this is because relativesource is listview and it works on complete listview. I also tried changing the relative source to ListviewItem but that didn't trigger anything. Can someone help me please. Do i need to change something here ?
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding MU_Identifier}" IsChecked="{Binding DataContext.Assignm, RelativeSource={RelativeSource FindAncestor, AncestorType=ListView}}">
</CheckBox>
</DataTemplate>
</GridViewColumn.CellTemplate>

Because your binding for IsChecked property is Assignm property which seems to be one property of your view model.
If there is a boolean property named Assignm for the data model of the DataSource of ListView, then just change the binding like this: {Binding Assignm}, as Tag property does.

All your items are bounded to a single property, so when one item changes a property in your context it changes on other items.
To provide correct work all your items from ItemsSource should have property IsChecked.
Check this Example

Related

WPF Datagrid selecteditem = null in MVVM

I'm trying to work with a datagrid using the MVVM pattern. The problem is that whenever I change the VM property which is binded to SelectedItem to null, the View doesn't "deselect" the currently selected item. This is my binding in xaml:
<DataGrid Grid.Column="0" Grid.Row="0"
ItemsSource="{Binding Path=Users}"
AutoGenerateColumns="False"
CanUserAddRows="False"
IsReadOnly="True"
SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}">
The SelectedItem binding works from the view to the VM thus in the SelectedUser property I always have the selected object. The problem is that in the VM I'm doing some stuff which sometimes changes the SelectedUser property to null so I would expect the datagrid to deselect the row as well. Instead, it remains selected and if I try to click on the same row, the property doesn't update. If I click on any other row, the property changes as expected.
Is there a way to make the datagrid deselect if it's binded property is set to null? Also I'm looking for a MVVM solution as I don't want to write code behind. I can solve this by writing code behind so don't waste time offering such solutions :)
l.e.: this is my property in the VM:
public RPLUser SelectedUser
{
get
{
return selectedUser;
}
set
{
selectedUser = value;
OnPropertyChanged("SelectedUser");
}
}
Thanks in advance!
I recommend to check the Output Window in visual studio and see if any Binding is failing.
Are you sure when you select something, the selection updates into the SelectedUser property?
Did u put a breakpoint in setter of SelectedUser and see that it is hitting when you select something on the datagrid?
The reasons for this Binding to break could be many ...
SelectedUser is of different type than individual Users.
SelectedUser does not match by reference with any items in Users.
How and where are you setting null?
The following code in my case works perfectly fine...
<tk:DataGrid MaxHeight="200" AutoGenerateColumns="False"
ItemsSource="{Binding}"
SelectedItem="{Binding MySelItem,
ElementName=MyDGSampleWindow,
Mode=TwoWay}"
IsReadOnly="True">
<tk:DataGrid.Columns>
<tk:DataGridTextColumn Header="Key"
Binding="{Binding Key,
Mode=OneWay}"/>
<tk:DataGridTextColumn Header="Value"
Binding="{Binding Value,
Mode=OneWay}"/>
</tk:DataGrid.Columns>
</tk:DataGrid>
When I set MyDGSampleWindow.MySelItem as null, the datagrid propertly deselects. Perhaps you might need to give us more input on how are you actually setting the value as null.
Did you try setting IsSynchronizedWithCurrentItem="True" in the xaml properties for the DataGrid? AFAIK, this will allow you to unselect it by setting the SelectedUser to null.
I cannot test it at the moment, but you could also try to add this in the setter of your property:
set
{
selectedUser = value;
OnPropertyChanged("SelectedUser");
ICollectionView collectionView = CollectionViewSource.GetDefaultView(Users);
collectionView.MoveCurrentTo(selectedUser);
}
(For ICollectionView to do anything, you will need to have IsSynchronizedWithCurrentItem set)
Like I said, I cannot test this right now. Also, the setter of the property is probably not the best place to put it. Maybe create an event handler for the PropertyChangedevent locally and put that logic there.
Let me know if it helps, else I'll see if I can run a short test...
Yeah may need to add the XAML UpdateSourceTrigger to update the UI.
SelectedItem="{Binding SomeProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
The DataGrid will not Deselect it automatically as DataGridRow's IsSelected property should be set to False.
You can do that by Setting a style on DataGrid.. like
<Style x:Key="dataGridRowStyle"
BasedOn="{StaticResource {x:Type WPFToolkit:DataGridRow}}"
TargetType="{x:Type WPFToolkit:DataGridRow}">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
</Style>
The IsSelected property should be the of the object i.e in your case RPLUser should have a property Isselected
Then before you set the SelectedUser to null... just do SelectedUser.IsSelected=False
And dont forget to attach this style to the DataGridRowStyle in Datagrid
I am using WPFToolkit you can modify the style if you are targetting .NET 4.0

Combobox's SelectedValue (or SelectedItem) OneWay binding not working. Any ideas?

In the below window, the Existing Reports combo is bound to an observeablecollection of reportObjects. I have a reportObject property currentReport bound to the combo's SelectedValue property, OneWay. However, that's not working when bound in XAML.
SelectedValue="{Binding currentReport, Mode=OneWay}"
TwoWay binds fine, but I can't do it that way without writing an undo() method to the reportObject class. I'm binding the currentReport's properties to the various textboxes for editing. I want to bind OneWay so the source doesn't get changed. The currentReport's properties are all TwoWay bound to the corresponding textboxes so when I update the table in SQL [Save], it'll pull from that object, who's data is current.
<TextBox Text="{Binding currentReport.reportName, Mode=TwoWay}"
All of the properties bound from currentReport to the textboxes work fine as well. The only problem is the OneWay binding from the SelectedValue to the currentReport object. Does anyone have any ideas how to get this to work? I saw there was a bug, but the post I saw was 2009.
Sorry about the yellow. Not my idea. =)
EDIT: Added this XAML just in case.
<ComboBox ItemsSource="{Binding reportsCollection}" SelectionChanged="cboReports_SelectionChanged"
DisplayMemberPath="displayName"
SelectedValue="{Binding currentReport, Mode=TwoWay}"
x:Name="cboReports" Width="342" Height="40" VerticalAlignment="Center"/>
Forget about you need to change values - that is a separate problem - need to review your data design. Start with the UI problem question. If you want a user to be able to select an item from a combo box then it must have two way binding. Your first question is SelectedValue="{Binding currentReport, Mode=OneWay}" is failing why?

MVVM ListBox controlling a Content Control

I've been going round in circles with this for a couple of days, and I'm hoping a WPF guru can see where I'm going wrong.
I'm setting CurrentViewModel in code. The Selected item of my ListBox and the Content of my ContentControl bind correctly. But when changing the selected item in the Listbox via the UI the CurrentViewModel is being set but the Content Control is not being updated.
I'm using a data template to map my Views and View Models.
<DataTemplate DataType="{x:Type ViewModel:MyViewModel}">
<View:MyView />
</DataTemplate>
I have a ListBox which is bound to an observable collection of ViewModels. The Selected Item is bound to the current view model.
<ListBox ItemsSource="{Binding MyViewModelCollection}" DisplayMemberPath="DisplayName" SelectedItem="{Binding CurrentViewModel, Mode=TwoWay}"/>
I also have a content control that is also bound to the CurrentView Model
<ContentControl Content="{Binding CurrentViewModel, Mode=TwoWay}"/>
This is the property that they are both bound to
public MyViewModel CurrentViewModel
{
get
{
return _currentViewModel;
}
set
{
if (_currentViewModel== value) return;
_currentViewModel= value;
OnPropertyChanged("CurrentViewModel");
}
}
I've edited the names for clarity and removed formatting information.
Any help greatly appreciated.
Cheers,
Daniel
EDIT: Came across the link How can I debug WPF bindings?. I set a break point on the Content binding and it does indeed only get called once when the binding is first set.
You should not be setting TwoWay as the mode on your ContentControl:
<ContentControl Content="{Binding CurrentViewModel, Mode=OneWay}"/>
This is because you intend your ContentControl to read the value, but never write it.
As an aside, you can also bind the ContentControl to the currently selected item in the collection, rather than to that property by doing this:
<ListBox ItemsSource="{Binding MyViewModelCollection}"
DisplayMemberPath="DisplayName"
IsSynchronizedWithCurrentItem="True"/>
<ContentControl Content="{Binding MyViewModelCollection/}"/>
The "slash" (/) at the end of the collection indicates the current item selected in the collection and setting that current item property is as simple as setting the IsSynchronizedWithCurrentItem equal to true.
A lot of times I find with this combination, I really don't need the extra property on my view model.
Anyway, I hope this helps.

WPF UserControl in DataTemplate within ItemsControl - how to bind to parent of ItemsSource

The subject line says it all really! I have a user control which can be bound successfully to, say, a Fullname object - i.e. it works ok.
I now need to show a list of these and, again, this works ok when the control is in a DataTemplate within ItemsControl.Template.
But, the control has a property (InEditMode) that is not a property of the Fullname object but of the object that has the FullnameList property to which the ItemsControl is bound, via ItemsSource. This InEditMode property works fine when the control is not in a list and is bound to parent sibling properties named, say, ParentInEditMode and ParentFullname.
The question is - what style of binding expression is required to 'get at' the edit mode property of the parent object when the control is an ItemsControl?
Or, should I re-design the Fullname object to contain an EditMode property?
Many thanks in advance!
Update:
The item (i.e. that which is in collection bound to the ItemsControl) does NOT have such a property. Code is very simple:
<ItemsControl ItemsSource="{Binding Path=FullnameList}">
...then...
<ItemsControl.ItemTemplate>
<DataTemplate>
<jasControls:NameView
NameValue="{Binding Path=.}"
InEditMode= ??????? />
The overall parent (the viewmodel for the window) has properties:
FullnameList
ParentInEditMode
Fullname (single item for testing NameView which works perfectly with this xaml outside of any list control using:
<jasControls:NameView NameValue="{Binding Path=Fullname}" InEditMode="{Binding Path=ParentInEditMode}"/>
I would like to apply the edit mode to the entire collection - making that flag part of Fullname does not seem right!?
I have found an answer to my own question, which I hope will help others.
The working syntax I have is this:
<StackPanel>
<ItemsControl ItemsSource="{Binding Path=FullnameList}">
...then...
<ItemsControl.ItemTemplate>
<DataTemplate>
<jasControls:NameView
NameValue="{Binding Path=.}"
InEditMode= "{Binding DataContext.ParentInEditMode,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}}}" />
This correctly picks up the property that is a sibling of FullnameList and passes it to the data template item. More by luck than judgement, but I hope this is a valid way to do this!
For each Item in ItemsSource, ItemsControl creates the specified DataTemplate and to its DataContext it assigns the respective Item. Now every DataTemplate can bind to its item in its data context.
So I suppose your item does have a property "ParentInEditMode"; there should be no issue with binding to that property.
If it doesn't work, please update your question with some code.

How to bind to a property of the ViewModel from within a GridView

I'm using the MVVM design pattern, and the DataContext of my View is set to a ViewModel.
In my View, I have a ListView/GridView with ItemsSource bound to a DataTable. One of the GridViewColumns has a CellTemplate that presents a Button. I want the IsEnabled property of the button to be bound to the SelectButtonsEnabled property of my ViewModel.
Using IsEnabled="{Binding Path=SelectButtonsEnabled}" doesn't work because my DataTable doesn't have a column named "SelectButtonsEnabled". The property I'm trying to bind to is global for the whole ViewModel, not specific to a row of the DataTable.
I think I need some kind of RelativeSource tag, but all my attempts thus far have failed.
Thanks.
Well, I don't know if this is the most succinct way to do it, but this works:
IsEnabled="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.SelectButtonsEnabled}"

Resources