Getting ListBox multiselect Items with Binding in WPF - c#

Is there any way of getting the items of a multiselect in a listbox without using the code behind, but whith just the binding?
I know that I can do a foreach on the code behind etc.. But I'm guessing if there is a cleaner solution with just the binding between XAML and ViewModel.
On some of the listboxes the IsSelected property is used to set multiple items selected at the page loading.
Thanks for the help.

You can send the SelectedItems as a command parameter. For example, you can get the listbox's SelectedItems in a button's command like this.
<ListBox x:Name="listbox" ItemsSource="{Binding MyList}" SelectionMode="Multiple"/>
<Button x:Name="btn" Command="{Binding MyCommand}" CommandParameter="{Binding SelectedItems, ElementName=listbox}" Content="Get Selected Items"/>

Related

Using ItemTemplate and DataTemplate creates a button within ListView. Why?

I have a situation with a ListView. Inside the item template there is a DataTemplate and inside the DataTemplate there is a ListViewItem and it's content is bound. When I click I want to select the item but when I hover my mouse over it, it seems like there is a button created with the ItemTemplate and DataTemplate . At the moment, I can select item by clicking somewhere else within the same row, but that doesn't work if I select the button. I use SelectedItem and if you click on the button within the item, the SelectedItem will not fired.
The ListView is linked to an ItemSource, and SelectedItem of the ListView is bound to a property
Further information: language is C#, ide is Visual Studio 2010.
I will leave my xaml code below, Thanks.
XAML
<ListView x:Name="myListView"
Grid.Column="0"
Grid.Row="2"
Height="Auto"
Margin="0,0,0,0"
SelectionChanged="SchemaListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<ListViewItem Content="{Binding Path=Value}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C#
void ReadData(string id)
{
var data = ExampleData.GetData(id);
myListView.ItemsSource = data.Results;
}
I've tried binding without ItemTemplate and DataTemplate also tried to link source in xaml but that didn't work
You must not have a ListViewItem in the ItemTemplate of a ListView.
When the elements of the ItemsSource collection are not already ListViewItems (which they typically never are), the framework will automatically create a ListViewItem that becomes the "item container" element for each data item. This automatically generated ListViewItem uses the ItemTemplate as its ContentTemplate.
Besides that, use a ListBox instead of ListView when you do not set a ListView's View property.
So instead of a ListViewItem, use a ContentControl or perhaps a TextBlock:
<ListBox ...>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If there is nothing more than a single content element, simply set the DisplayMemberPath property:
<ListBox ... DisplayMemberPath="Value"/>

Binding Datagrid Item to Textboxes

I try to bind a selected item in my datagrid to some textboxes.
Sadly the textboxes wont be updated on change.
If you need more Informations fell free to ask.
In my view i try to bind the the data of the selected Item of the Datagrid to the Textboxes.
in the Textboxes there can be a new employee you want to add or one of the Datagrid that you want to edit.
<TextBox Name="TxtName" Text="{Binding Employee.LastName}" Grid.Column="1" Grid.Row="0"></TextBox>
<TextBox Name="TxtFirstName" Text="{Binding Employee.FirstName}" Grid.Column="3" Grid.Row="0"></TextBox>
<TextBox Name="TxtDateOfBirth" Text="{Binding Employee.DateOfBirth, StringFormat=d}" Grid.Column="1" Grid.Row="1"></TextBox>
<ComboBox Name="CmbGender" SelectedItem="{Binding Employee.Gender}" ItemsSource="{Binding Genders}" DisplayMemberPath="Short" Grid.Column="3" Grid.Row="1"/>
<DataGrid Name="GrdAllEmployees" ItemsSource="{Binding Employees}" SelectedItem="{Binding SelectedEmployee}" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="4" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChanged}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
In my ViewModel i set the Value of the Selected Employee to the Employee that is shown in the Textboxes and raise the Events for both.
public Employee SelectedEmployee
{
get { return _selectedEmployee; }
set
{
_selectedEmployee = value;
NotifyPropertyChanged("SelectedEmployee");
_employee = _selectedEmployee;
NotifyPropertyChanged("Employee");
}
}
After this the values are correct on debugging. but the view will not be updated.
There is a much simpler way of displaying values from the selected item of the DataGrid, or in fact any collection control in WPF. That is to use the Selector.IsSynchronizedWithCurrentItem property. When you set this to true, then you can reference the selected item from that collection using the / notation, which means the current item. Try something like this:
<StackPanel>
<DataGrid ItemsSource="{Binding Employees}" IsSynchronizedWithCurrentItem="True" />
<TextBlock Text="{Binding Employees/Name}" />
</StackPanel>
This would display the Name property value from the currently selected item in the DataGrid. Further information... from the Binding.Path Property page on MSDN:
When the source is a collection view, the current item can be specified with a slash (/). For example, the clause Path=/ sets the binding to the current item in the view. When the source is a collection, this syntax specifies the current item of the default collection view.
Property names and slashes can be combined to traverse properties that are collections. For example, Path=/Offices/ManagerName specifies the current item of the source collection, which contains an Offices property that is also a collection. Its current item is an object that contains a ManagerName property.
It worked for me after i replaced my own classes for the RelayCommand and ViewModelBase with the ones of MVVMlight, that i downloaded from nuget.
https://mvvmlight.codeplex.com/
I just had to change the NotifyPropertyChanged with RaisePropertyChanged.
But also thanks to #Sheridan for his advice.

Two way data Binding issue with combo box - WPF

I have a View that contains a Combobox. The Combobox SelectedItem property is data bound to SelectedX property of View Model as two way data binding. When the viewModel is initialized, the SelectedX property is set correctly. But after that when the view renders, it resets the value of SelectedX(since the binding is two-way).
So the two way data binding for the Combobox is basically not working. Please advise.
This is the xaml for my view. I initialize the View model first with apprpriate values for Relationships and SelectedX. When the view renders, the combo box resets the value for SelectedX. (I figured that by adding breakpoints). Hope this helps
<ComboBox Grid.Row="1" Grid.Column="1" Margin="5" Background="White" BorderBrush="DarkGray"
SelectedItem="{Binding SelectedX, Mode=TwoWay}"
ItemsSource="{Binding Relationships}" DisplayMemberPath="Value"
SelectedValuePath="Value" SelectedValue="{Binding Key, Mode=TwoWay}"
IsEditable="False" IsReadOnly="True" />
SelectedValue="{Binding Key, Mode=TwoWay}"
This will change the SelectedItem to its SelectedValue.

How to get a value from an edited TextBox before a ListBox item is selected?

I have a Silverlight application with a formular. The formular has a TextBox and a ListBox.
<TextBox Text="{Binding Value, Mode=TwoWay}/>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListBox>
I focus the TextBox and write something into it. After this I select an item in the ListBox. The ViewModel seems to set "SelectedItem" BEFORE "Value". Why? How can I fix the order? I mean I need to process the TextBox before the ListBox.
Thanks
Unfortunately, that looks like a bug. Same example on WPF will cause the TextBox to be set before the ListBox. You would have to find another way of doing what you want by slightly changing the logic of how you app UI functions.
You can update your TextBox Text property binding on TextChanged event, not LostFocus how it is now. Here is a sample.
The TextboxBinding is by default updating on LostFocus, try changing your binding to this:
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}/>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
</ListBox>

WPF ListBox in Popup setting null SelectedItem on PopupClose

I have a WPF Popup, which is structured as below (with some senstitive stuff removed)...
<Popup>
<Border>
<StackPanel>
<ListBox
ItemSource="{Binding X}"
SelectedItem="{Binding Y}"
IsSynchronizedWithCurrentItem="True"/>
<Separator/>
<MenuItem Command="{Binding Path=EditModeCommand}"/>
</StackPanel>
</Border>
</Popup>
The ListBox works as expected, the list populates from the binding, and the selected item feeds back to the collection correctly.
However when the MenuItem fires its command, the SelectedItem binding fires as well, setting the SelectedItem to null. Is there a way to preserve the SelectedItem when the listbox is not the focus of the click?
Try setting the SelectedItem property before the ItemSource property in the declaration.

Categories