I've got a wpf mvvm application up and running. In one of my views I've got a listbox where one column is a combobox. I thought that I had everything working, but... I ended up here.
When I select a value in the combobox in one row, all rows are changed. I've tried a lot of things and i'm stuck.
Here's my xaml:
<ListView ItemsSource="{Binding Path=Properties.OutputGroups, Mode=TwoWay}">
<ListView.View>
<GridView >
<GridViewColumn Header="Output" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.Outputs}" SelectedValue="{Binding Path=Obj.OutputID, Mode=TwoWay}" IsSynchronizedWithCurrentItem="False" DisplayMemberPath="DisplayName" SelectedValuePath="ID" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Duration">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=Obj.Duration}" BorderThickness="0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="State" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=Obj.State}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I'm not positive about this, so I apologize if this is not correct, but according to what I have read on MSDN here, I think it might have to do with the "isSynchronizedWithCurrentItem" property. Try switching this property to "true," and see if that fixes your problem.
Like I said, I'm not positive this is where the problem is, but it seems to me like you are wanting the data to be synchronized with the current item, hence why that property is throwing up a flag to me.
I really hope this helps! (And I truly apologize if it doesn't)
Related
I have this problem with my C# WPF app:
I have the checkboxes on every row but when I select (random) one or more checkboxes I noticed that other checkboxes on other rows (when I scroll to see the other rows) are selected, too. It's like there would be a function or something that checks automatically other checkbox different of those selected by me.
There is no C# code for the checkboxes (just the definitions of the functions for Checked, Unchecked). I use a query and ItemSource to fill the Datagrid.
So, is there a way to avoid the automatic selection of other checkboxes ?
Thankx
My XAML code:
<DataGridTemplateColumn x:Name="colonnaChiusoF" Header="Cf" Width="26">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=sc1, Mode=TwoWay}" Checked="checkedF" Unchecked="uncheckedF" Margin="0" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Actually it happens with other objects, too. For example, in this code the buttons and checkboxes are selected automatically random if I select/deselect some of them:
<ListView Name="listaView" ItemsSource="{Binding Path=Table}" Height="200" Width="400" ScrollViewer.VerticalScrollBarVisibility="Visible" IsSynchronizedWithCurrentItem="True" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}">
<ListView.View>
<GridView>
<GridViewColumn Header="Idprev" DisplayMemberBinding="{Binding Path=idPrev}" />
<GridViewColumn Header="DataPrev" DisplayMemberBinding="{Binding Path=dataPrev}" />
<!--<GridViewColumn Header="Test3" DisplayMemberBinding="{Binding Test3}" /> -->
<GridViewColumn Header="Chiudi">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Margin="0" BorderThickness="0" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Button">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ToggleButton IsChecked="True">Button Text</ToggleButton>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The C# code:
DbDataAdapter da = daoObject.list_3(0, 0, arrayFilter);
DataSet dataset = new DataSet();
da.Fill(dataset);
listaView.DataContext = dataset.Tables[0].DefaultView;
Well, the problem should be the virtualization. If I UNCHECK "Enable row virtualization" it seems the checkboxes remain as I select them so there is no random automatically check-uncheck.
The problem now is that the records are loaded slower than with the virtualization enabled.
Hello Can anyone tell where did I made mistake in code below,
<ListView x:Name="ServiceListView"
Loaded="ServiceListView_Loaded"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
VirtualizingPanel.IsVirtualizing="True"
GridViewColumnHeader.Click="ServiceListSort"
ScrollViewer.IsDeferredScrollingEnabled="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<RadioButton IsChecked="{Binding Status}" x:Name="StartService" Checked="StartService_Checked" GroupName="{Binding ServiceName}" Style="{DynamicResource StartServiceStyle}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="50" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<local:InvertBooleanConverter x:Key="InvertBooleanConverter" />
</DataTemplate.Resources>
<RadioButton IsChecked="{Binding Status, Converter={StaticResource InvertBooleanConverter}}" Checked="StopService_Checked" x:Name="StopService" GroupName="{Binding ServiceName}" Style="{DynamicResource StopServiceStyle}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="120" DisplayMemberBinding="{Binding ReccomendedStatus}">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Recommendation"/>
</GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="750" DisplayMemberBinding="{Binding ServiceName}">
<GridViewColumn.Header>
<GridViewColumnHeader Content="Description"/>
</GridViewColumn.Header>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Currently it has 20-40 items which are visible only 7, it takes around 5-7 seconds, removing both radiobutton Checked event time reduces to 2-4 seconds
private void ServiceListView_Loaded(object sender, RoutedEventArgs e)
{
ServiceListView.ItemsSource = DATA_CONTROLS.ServiceData.Values;
}
public static Dictionary<int, DataObject> ServiceData = new Dictionary<int, DataObject>();
Why it takes so long to show in msdn I saw that showing 1000 items only takes 1.6 second, why this method which contains 20-40 items takes 5-7 seconds? I really need to know what causing such performance issue. Thank you.
Found a issue: While I setting: ServiceListView.ItemsSource = DATA_CONTROLS.ServiceData.Values; It automaticly fires radiobutton events which would cause such performance drop, also usage IsAsynch improved also performance.
Add 'IsAsync=True' in your ListView,to increase a performance
How do I access a control in XAML that is nested in a GridViewColumn.CellTemplate? By accessing the combo box I want to set its ItemsSource in the code behind.
Code:
<GridViewColumn Width="80">
<GridViewColumnHeader Content="UseCLUT"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Path=UseCLUT}" Style="{StaticResource GridBlockStyle}"/>
<ComboBox x:Name="combTrueFalse" SelectedItem="{Binding Path=UseCLUT}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I have named the comboBox as combTrueFalse and tried to referenced it in the code behind but it could not be found.
I find a work around to the problem.
I have set the collection of the combo box to a class which contains the collection for the combox's selection.
The mainWindow class contains the data class's variable.
ItemsSource="{Binding ElementName=mainWindow, Path=data.comboxTFSmall}"
Meaning to say I have set the combox's item towards a Class which contains the collection and not from the code behind.
<GridViewColumn Width="80" >
<GridViewColumnHeader Content="UseCLUT"/>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Path=UseCLUT, Mode=TwoWay}" Style="{StaticResource GridBlockStyle}"/>
<ComboBox ItemsSource="{Binding ElementName=mainWindow, Path=data.comboxTFSmall}" SelectedValue="{Binding Path=UseCLUT}" Style="{StaticResource GridEditStyle}" />
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
Please do correct me if you find that my explanation is misleading thanks.
regards
I have a this code:
<ListView Height="238"
HorizontalAlignment="Left"
Name="listView1"
VerticalAlignment="Top"
Width="503"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding ID}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding ID}" Header="ID" />
<GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
That produce this window:
How do I know how many checkboxes are selected, and get the value Tag of each CheckBox that is selected?
i know it's old but for posterity if people stubble upon this here's the solution
<ListView Height="238"
HorizontalAlignment="Left"
Name="listView1"
VerticalAlignment="Top"
Width="503"
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
SelectionChanged="listView1_SelectionChanged">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding ID}" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}}, Path=IsSelected}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding ID}" Header="ID" />
<GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
then in the cs file code this in the listView1_SelectionChanged
private List<MyObject> lstMyObject = new List<MyObject>();
private void listView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (MyObject item in e.RemovedItems)
{
lstMyObject.Remove(item);
}
foreach (MyObject item in e.AddedItems)
{
lstMyObject.Add(item);
}
}
lstMyObject should be same type as your object binded to the list. and the code will simply add and remove reference to items of the original list to that list.
Now all you will have to do is loop through that list which will contain only the actually selected items. this works for single selection only except that the lstMyObject will just contain 1 record all the time.
It should be as simple as binding the IsChecked property of the CheckBox to a property on the ViewModel (you may need to add a new property if it doesn't already exist). Then, once the button is clicked, you would just iterate over all the items in the collection, and delete the ones that are checked (based on the value of the property on the ViewModel).
A suggestion...
Just like the Tag property in all Windows controls, I've always had a Tag property in all my data models for general purpose use at run-time. I use that property to hold checked state of the item in a ListView. In other circumstance, I use them to hold complex objects as well.
If I were to say "the heck with it!", I could just give my ListView with SelectionMode="Multiple" a name, and be able to get all of the selected items very easily. But I'm trying to stick to MVVM as much as possible, and I want to somehow databind to an ObservableCollection that holds the value from the Name column for each selected item. How in the world do you do this? Single selection is simple, but the multi selection solution is not obvious to me with my current WPF / MVVM knowledge.
I read this question on SO, and while it does give me some good insight, I don't know how to add the necessary binding to a row, because I am using a ListView with a GridView as its View, not a ListBox.
Here's what my XAML basically looks like:
<ListView DockPanel.Dock="Top" ItemsSource="{Binding ClientPreview}" SelectionMode="Multiple">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Address">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Address}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
It sounds like the right thing to do is to databind each row's IsSelected property to each object stored in the ObservableCollection I'm databinding to. I just haven't figured out how to do this.
Write ItemContainerstyle on the ListView and put a Setter to do the binding to your ViewModel 'IsSelected' property
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected,Mode=OneWayToSource}"/>