Not able to display ListView item to textbox - c#

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;

Related

Get the value of a ListView item with button click

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;
}

WPF How to set checkbox in Gridview binding in code behind

style that I have to create in code-behind. It has a checkbox that looks like this..
<GridView>
<GridViewColumn Width="30">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel>
<CheckBox/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>-->
<GridViewColumn Header="Groups" DisplayMemberBinding="{Binding Groups}"/>
<GridViewColumn Header="SiteTitle" DisplayMemberBinding="{Binding SiteTitle}"/>
<GridViewColumn Header="SiteUrl" DisplayMemberBinding="{Binding SiteUrl}"/>
</GridView>
How I do in code-behind?
Just add this style in Resources and give it a x:Name.Let's assume the given name is CustomCheckboxTemplate , then a sample code will look like :
DynamicallyCreatedCheckbox.Style = (Style)FindResource("CustomCheckboxTemplate");
Hope this helps :)

Deleting all items from listview

New to Visual Studio, trying to convert a VM deployment GUI I have in another language to a wpf application. I am 80% of the way there, just a couple of questions. The GUI has a number of input fields for the user to fill out. The when a button is clicked those input fields populate a listview. The listview is declared like so:
<ListView x:Name="lstOut" ScrollViewer.HorizontalScrollBarVisibility="Visible" HorizontalAlignment="Left" Height="205" Margin="10,394,0,0" VerticalAlignment="Top" Width="1294"
ItemsSource="{Binding MyItems}" SelectionMode="Single">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="CPU" DisplayMemberBinding="{Binding CPU}"/>
<GridViewColumn Header="RAM" DisplayMemberBinding="{Binding RAM}"/>
<GridViewColumn Header="IP Address" DisplayMemberBinding="{Binding IP}"/>
<GridViewColumn Header="Subnet" DisplayMemberBinding="{Binding Subnet}"/>
<GridViewColumn Header="Port Group" DisplayMemberBinding="{Binding PortGroup}"/>
<GridViewColumn Header="Gateway" DisplayMemberBinding="{Binding Gateway}"/>
<GridViewColumn Header="DNS" DisplayMemberBinding="{Binding DNS}"/>
<GridViewColumn Header="Description" DisplayMemberBinding="{Binding Description}"/>
<GridViewColumn Header="Template" DisplayMemberBinding="{Binding Template}"/>
<GridViewColumn Header="Host" DisplayMemberBinding="{Binding Host}"/>
<GridViewColumn Header="Site Code" DisplayMemberBinding="{Binding Site}"/>
<GridViewColumn Header="Folder" DisplayMemberBinding="{Binding Folder}"/>
<GridViewColumn Header="DataStore" DisplayMemberBinding="{Binding Datastore}"/>
<GridViewColumn Header="Patch Method" DisplayMemberBinding="{Binding Patch}"/>
<GridViewColumn Header="HDD1 Size" DisplayMemberBinding="{Binding HDD1Size}"/>
<GridViewColumn Header="HDD1 Format" DisplayMemberBinding="{Binding HDD1Format}"/>
<GridViewColumn Header="HDD2 Size" DisplayMemberBinding="{Binding HDD2Size}"/>
<GridViewColumn Header="HDD2 Format" DisplayMemberBinding="{Binding HDD2Format}"/>
<GridViewColumn Header="HDD3 Size" DisplayMemberBinding="{Binding HDD3Size}"/>
<GridViewColumn Header="HDD3 Format" DisplayMemberBinding="{Binding HDD3Format}"/>
<GridViewColumn Header="HDD4 Size" DisplayMemberBinding="{Binding HDD4Size}"/>
<GridViewColumn Header="HDD4 Format" DisplayMemberBinding="{Binding HDD4Format}"/>
<GridViewColumn Header="HDD5 Size" DisplayMemberBinding="{Binding HDD5Size}"/>
<GridViewColumn Header="HDD5 Format" DisplayMemberBinding="{Binding HDD5Format}"/>
</GridView>
</ListView.View>
For adding the collection of items from the GUI to the listview, as well as exporting to csv later in the code, I declared a collection like so:
public ObservableCollection<MyItem> MyItems { get; set; } = new ObservableCollection<MyItem>();
I am able to delete a selected item from the listview in this manner, which seems to work well:
private void DeleteRow(object sender, RoutedEventArgs e)
{
MyItem line = lstOut.SelectedItem as MyItem;
if (line != null)
MyItems.Remove(line);
}
What I am stuck on (one of the things anyway), is deleting everything from the listview. I tried both of these methods:
lstOut.Items.Clear();
lstOut.Items.Remove(MyItems);
But get an error either way that this is not valid when ItemsSource is in use. I tried lstOut.ItemsSource, but could not find a way to clear all content.
I ended up doing it like this, which seems to work (marginally):
for (int i=0; i < lstOut.Items.Count; i++)
{
MyItems.Remove(MyItems[i]);
}
The problem with this method is that is removes half the item count with each button click. If I have 9 items in the listview it cuts it down to 4, another click cuts it down to 2, then 1, then finally deletes.
Can anyone suggest an easier way to delete all content in one action? I am sure it is something stupid simple I am missing, but would appreciate any suggestions.
ICollection<T> in general and ObservableCollection in particular have method Clear()
so the correct way (and the only way when you follow MVVM) is
MyItems.Clear();
using Clear with ObservableCollection is much more effective than multiple calls to Remove, because ObservableCollection raises notifications when items inside are added/removed/replaced. One notification about Clear is faster than numerous notifications about Remove
why this code acts weirdly?
for (int i = 0; i < lstOut.Items.Count; i++)
{
MyItems.Remove(MyItems[i]);
}
let's say initial state is [1,2,3,4], i = 0, lstOut.Items.Count = 4
after first iteration is becomes [2,3,4], i = 1, lstOut.Items.Count = 3
so i points to item 3 !
item 2 was skipped !
a correct loop should be reversed (from last item in collection to first)
for (int i = MyItems.Count - 1; i >= 0; i--)
{
MyItems.RemoveAt(i);
}
or another way is to remove items at 0 position, while there items:
while(MyItems.Count > 0)
{
MyItems.RemoveAt(0);
}

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());

Binding a ListView to an ObservableCollection of ArrayList items without named properties

Firstly:
<ListView Height="259" HorizontalAlignment="Left" Margin="7,6,0,0" Name="dataListView" VerticalAlignment="Top" Width="899">
<ListView.View>
<GridView>
<GridViewColumn Width="240" Header="Test" />
<GridViewColumn Width="50" Header="Result" />
<GridViewColumn Header="Column 3" />
</GridView>
</ListView.View>
</ListView>
is the definition in my XAML file.
Then when a test starts, I run:
dataListView.ItemsSource = tr.TestResultCollection;
In TestRunner.cs, I have created the Observable Collection of ArrayLists as such:
ObservableCollection<ArrayList> _testResultCollection = new ObservableCollection<ArrayList>();
and publicly refer to them as such:
public ObservableCollection<ArrayList> TestResultCollection
{ get { return _testResultCollection; } }
Finally when I add to the collection, I use :
_testResultCollection.Add(SummaryVerificationTestCase1(dbs, dbd));
which adds an ArrayList to the collection. (Yes, a collection of ArrayLists, I know...)
However, what gets displayed in each Column is (Collection), (Collection, (Collection).
I see why. However, I'm not entirely certain what the neatest way around is. Normally in each GridViewColumn you give a binding like:
DisplayMemberBinding="{Binding TestResult}"
But the ArrayList doesn't have named components, just indices (0-2).
Is there a way to bind each column to the individual indices? Or have I missed something simple already?
Specify an index in the binding path:
<GridViewColumn Width="240" Header="Test" DisplayMemberBinding="{Binding Path=[0]}"/>
<GridViewColumn Width="50" Header="Result" DisplayMemberBinding="{Binding Path=[1]}"/>
<GridViewColumn Header="Column 3" DisplayMemberBinding="{Binding Path=[2]}"/>

Categories

Resources