Get the value of a ListView item with button click - c#

I have a ListView that gets its values from a database, with the last column being buttons. What I am trying to do, is that when a button is clicked, the value of the Name in the same row will be returned.
Here's the relevant part of my XAML code:
<Grid Grid.ColumnSpan="2">
<ListView Name="PeopleList">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding [Name]}" />
<GridViewColumn Header="Phone" DisplayMemberBinding="{Binding [Phone]}" />
<GridViewColumn Header="Email" DisplayMemberBinding="{Binding [Email]}" />
<GridViewColumn Header="Actions" Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button Content=">" Click="ActionButton_Click"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>

You should be able to get the exact Button that was clicked from the sender argument of the Click event. From there you should be able to get Button.DataContext, which would hold a reference to the item that is being displayed on that row.
It would be something like:
private void ActionButton_Click(object sender, EventArgs args)
{
var rowItem = (sender as Button).DataContext as People;
string name = rowItem.Name;
}

Related

Create a click event on ListViewItem programmatically in WPF

I'm making a WPF app, this app has a UserControl, which has a list view.
I tried to create a click event listener but i never got it to work right, and i havend find anything to solve it
I fill this list view items with an object like this:
List<AsesoriaClass> listaAsesorias = phpClass.getListaAsesoriasAsesor(asesor.ID);
foreach (var asesoria in listaAsesorias)
{
AsesoriaTable data = new AsesoriaTable(asesoria.AsesoriaID.ToString(), asesoria.ClienteNombre + " " + asesoria.ClienteApellidos, asesoria.FechaInicio.ToString(), asesoria.FechaFinal.ToString());
this.ListView.Items.Add(data);
}
And this is the XAML of the User Control:
<ListView x:Name="ListView">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Path=Id}" Width="100"/>
<GridViewColumn Header="Cliente" DisplayMemberBinding="{Binding Path=Cliente}" Width="300"/>
<GridViewColumn Header="Inicio" DisplayMemberBinding="{Binding Path=Inicio}" Width="200"/>
<GridViewColumn Header="Final" DisplayMemberBinding="{Binding Path=Final}" Width="200"/>
</GridView>
</ListView.View>
</ListView>
I want to make a click listener so, when i click on an item something happens (to start i just want it to show a mesage box). how do i do this?
You can simply attach an Event Handler on SelectionChanged. Like this
ListView.SelectionChanged += LstOnSelectionChanged;
Where LstOnSelectionChanged is a method.
private void LstOnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("Anything");
}

Not able to display ListView item to textbox

Hi all. When ListView item is double clicked it should display the corresponding data to text box, later i will write some code to update.
<p>Below is listview code on my xaml file</p>
<ListView Margin="534,233,10,18" Name="lvCus" MouseDoubleClick="ListViewItem_DoubleClick">
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="TbCus">
<GridViewColumn Header="CusID" Width="40" DisplayMemberBinding="{Binding Path=CusID}" />
<GridViewColumn Header="fn" Width="120" DisplayMemberBinding="{Binding Path=fn}" />
<GridViewColumn Header="Lastname" Width="120" DisplayMemberBinding="{Binding Path=ln}" />
<GridViewColumn Header="Dob" Width="100" DisplayMemberBinding="{Binding Path=dob}" />
<GridViewColumn Header="Age" Width="60" DisplayMemberBinding="{Binding Path=age}" />
</GridView>
</ListView.View>
</ListView>
Below is code at backend.
private void ListViewItem_DoubleClick(object sender, RoutedEventArgs e)
{
ListViewItem item = lvCus.SelectedItems[0];
txtfn.Text = item.SubItems[1].Text;
txtln.Text = item.SubItems[2].Text;
txtdob.Text = item.SubItems[3].Text;
}
I see red underline near the code lvCus.SelectedItems[0] , Error: cannot implicitly convert type 'object' to 'System.Windows.Controls.ListViewItem'. An explict conversion exists (are you missing a cast?)
Any help would be appreciated. Thanks.
You need to cast to your type of object say Customer
Customer custObj = (Customer)lvCus.SelectedItems[0];
Then you can access the properties
txtfn.Text = custObj.fn;
txtln.Text = custObj.ln;
txtdob.Text = custObj.dob;

GridViewColumnHeader.Click, How to detect which column was clicked?

Been messing with this and can't seem to figure it out. It seems that the object sender is actually the ListView.. so even though if I figure out how to get the GridViewColumn as a child... I don't know how to distinguish which column was actually clicked?
<ListView x:Name="SingleTweet_ListView"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
MouseLeftButtonUp="SingleTweet_ListView_MouseLeftButtonUp"
Height="200" Margin="5,5,5,5" FontSize="12"
GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler">
<ListView.View>
<GridView>
<GridViewColumn Header="Screen Name"
DisplayMemberBinding="{Binding Col1}" Width="112"/>
<GridViewColumn Header="Tweet"
DisplayMemberBinding="{Binding Col2}" Width="623"/>
</GridView>
</ListView.View>
</ListView>
void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e)
{
MessageBox.Show(((GridViewColumn)sender).Header.ToString());
//error cus the sender is actually the listview?
}
Sender will be ListView but you can check for OriginalSource which will be GridViewColumnHeader and can get column from it:
MessageBox.Show(((GridViewColumnHeader)e.OriginalSource).Column
.Header.ToString());

WPF ListViewItem item CheckBox. How to get all selected items?

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.

How to bind a ListView to an ObservableCollection<KeyValuePair<int,object>> inside a ViewModel in WPF?

Something like this:
public class EffectViewModel
{
public string Name ...
ObservableCollection<KeyValuePair<int,object>> settings
public ObservableCollection<KeyValuePair<int,object>> Settings
{
get {return this.settings;}
set
{
this.settings = value;
this.RaisePropertyChanged ( "Settings" );
}
}
}
Right now I am trying to bind it like this:
EffectWindowViewModel.Effects is of type ObservableCollection<EffectViewModel>.
<ListView Width="1000"
Height="600"
ItemsSource="{Binding EffectWindowViewModel.Effects}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Key}"
Header="Name" />
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Value}"
Header="Value" />
</GridView>
</ListView.View>
</ListView>
But I don't know how to specify .Settings property.
Any ideas?
your actual binding will not work cause EffectViewModel has no key and Value Property. i really dont know what your listview should display. if you want a list of EffectViewModels then the Itemssource is right. if you want further for each EffectViewModel to display the settings. then you need somekind of itemsscontrol with Itemssource={Binding Settings}. this itemsscontrol of course will need a itemsstemplate with your Key and Value.
i have no VS here atm, but your GridViewColumn needs a kind of CellTemplate. and this template should consist of a itemscontrol. because you have 2collections!
this code is probably not right but should take you in the right direction
<ListView Width="1000"
Height="600"
ItemsSource="{Binding EffectWindowViewModel.Effects}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Settings}">
<GridViewColumn.CellTemplate>
<DataTemplatex:Key="myCell4Settings">
<ListView ItemsSource="{Binding.}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Key}"
Header="Name" />
<GridViewColumn Width="Auto"
DisplayMemberBinding="{Binding Value}"
Header="Value" />
</GridView>
</ListView.View>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView>
</DataTemplate>
</GridView>
</ListView.View>
btw you could also use 2 lists independent. one parent Combobox or listbox (x:Name=parent) with itemssource=EffectWindowViewModel.Effects and a second ListView like you have, with the itemssource binding:
ItemsSource="{Binding ElementName=parent, Path=SelectedItem.Settings}"
You could try:
ItemsSource="{Binding ElementName=Settings, Path=EffectWindowViewModel.Effects}"

Categories

Resources