Edit TextView column on ListView WPF - c#

I'm Using WPF.
I have ListView with TextBox column and two checkboxs columns.
I want to edit the TextBox text by double click or something else.
What is the simple way to do that?
...
<GridViewColumn Header="Name" DisplayMemberBinding={Binding Path=fullName}" Width=500>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Name="txtName"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
...

Here is a sample way of doing this...
public partial class MainWindow : Window
{
public List<string> Items { get; set; }
public MainWindow()
{
InitializeComponent();
Items = new List<string>();
LoadItems();
DataContext = this;
}
private void txtName_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
TextBox currentTextBox = (TextBox)sender;
if (currentTextBox.IsReadOnly)
currentTextBox.IsReadOnly = false;
else
currentTextBox.IsReadOnly = true;
}
private void LoadItems()
{
Items.Add("Coffee");
Items.Add("Sugar");
Items.Add("Cream");
}
}
<Grid>
<ListView ItemsSource="{Binding Items}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Name="txtName" Text="{Binding Mode=OneTime}" IsReadOnly="True" MouseDoubleClick="txtName_MouseDoubleClick" Width="100"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>

Here is an example I have from an application that I wrote. The column JobName was to be user editable. This example allows the column to be editable and also gets rid of the border and lets the background blend into the row so it doesn't appear to have a text box in it.
Those can be edited out (BorderThickness="0" Background="Transparent").
My example binds to an MVVM ViewModel property called JobName and is set to be "TwoWay" so that changes to the view model will also reflect on the UI.
<ListView x:Name="lvJobs" HorizontalAlignment="Left" Height="628" Margin="30,62,0,0" ItemsSource="{Binding Jobs}"
SelectedItem="{Binding SelectedJob, Mode=TwoWay}" VerticalAlignment="Top" Width="335">
<ListView.View>
<GridView>
<GridViewColumn Header="Active" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive, Mode=TwoWay}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Job Name" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding JobName, Mode=TwoWay}" BorderThickness="0" Background="Transparent"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding User}" Header="User" Width="125"/>
</GridView>
</ListView.View>
</ListView>

Related

Implementing double-click event for ListView

I've seen plenty of examples of how to add a double-click event for each ListView item, but I can't figure out how to implement it to my code. The best example I found so far is this one in MS docs, but it still doesn't help me handle this :
<ListView Name="listViewItem" ClipToBounds="True" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" SizeChanged="ListView_SizeChanged" TextOptions.TextHintingMode="Animated" Margin="0,0,117,0">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="Task ID" Width="0">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TaskID}" TextWrapping="Wrap" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Tast Title" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TaskTitle}" TextWrapping="Wrap" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Task Deadline" Width="275">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TaskDeadline}" TextWrapping="Wrap" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Task Group" Width="150">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TaskGroup}" TextWrapping="Wrap" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Task Contact" Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TaskContact}" TextWrapping="Wrap" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Task Workers" Width="200">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TaskWorkers}" TextWrapping="Wrap" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I have a helpers class that sets values on load event ->
public void GetGridTasks(ref ListView listViewItem)
{
SqlCommand sqlCommandRefresh = new SqlCommand("", dataconnection);
sqlCommandRefresh.CommandText = "SELECT TaskID, TaskTitle, TaskDeadline, TaskGroup, TaskContact, TaskWorkers FROM Tasks";
SqlDataAdapter sqlAdapter = new SqlDataAdapter(sqlCommandRefresh);
DataTable dt = new DataTable("Tasks");
sqlAdapter.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
dr["TaskWorkers"] = dr["TaskWorkers"].ToString().Replace("||", ", ");
}
listViewItem.ItemsSource = dt.DefaultView;
}
This is basically TextBlocks inside GridView inside ListView. Can't really wrap my head around fixing this mess.
Just use the MouseDoubleClick Event from the ListView.
Example:
<ListView MouseDoubleClick="ListView_MouseDoubleClick">
//Items here
</ListView>
In your code behind you simply add an event handler for that
void ListView_MouseDoubleClick(object sender, MouseButtonEventArgs e){
var item = ((FrameworkElement) e.OriginalSource).DataContext
var myItem = item as *CastToWhateverTypeYouNeed*
if (item != null){
//Here you have your item
}
}

How to get all checked selected items from Listview in c# WPF

I want to get all the items in a listview that the checkbox has checked.
<ListView x:Name="lvwStudent" IsSynchronizedWithCurrentItem="True" SelectionMode="Multiple" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
<ListView.View>
<GridView>
<GridViewColumn Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="cboxSelected" Content ="{Binding ID}" Width="20" Height="20" BorderBrush="#FF0C6161" HorizontalAlignment="Center" HorizontalContentAlignment="Center" Tag="{Binding ID}" IsChecked="{Binding IsChecked}" Checked="cboxSelected_Checked_1" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="NO." Width="53">
<GridViewColumn.CellTemplate>
<DataTemplate >
<Label Content ="{Binding ID}" FontSize="14" HorizontalContentAlignment="Center"></Label>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="STUDENT NAME" Width="auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Content ="{Binding STUDENT_NAME}" FontSize="14" HorizontalContentAlignment="Center"></Label>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
when I click the select button I want to get all selected ID and store in an array.
private void btnSelect_Click(object sender, RoutedEventArgs e)
{
int[] selectedId;
if(lvwMachine.SelectedItems.Count > 0)
{
foreach(..... )
{
//add all selected id in array selectedId
}
}
List<Student>StudentList = new Students().getStudent();
List<ListViewItem> ITEM = new List<ListViewItem>();
foreach (var s in StudentList)
{
ListViewItem OneItem = new ListViewItem();
OneItem.Content = new Student()
{ID = s.ID, STUDENT_NAME = s.name};
ITEM.Add(OneItem);
lvwMachine.ItemsSource = ITEM;
}
You can try this:
lvwMachine.ItemsSource.Where(element => element.IsChecked).ToArray();

How To bind ListView values depends on combobox selected item?

Hi all i want to bind my listbox depends on combobox selected item here is my code
<StackPanel Orientation="Horizontal" >
<ComboBox Name="cmbID" Width="150" Margin="10" Height="30" SelectedItem="{Binding CmbSelected,Mode=TwoWay}" DisplayMemberPath="ID" ItemsSource="{Binding MyStudent,Mode=TwoWay}"/>
<Button Name="btnGetDetail" Margin="10" Command="{Binding getDetails}" Content="Get Details" Height="30" Width="90"/>
<TextBox Name="tbName1" Width="90" Height="30" Text="{Binding ElementName=cmbID,Path= SelectedItem.Sub}"></TextBox>
</StackPanel>
In Above code i am binding my combobox to one observable collection and want to bind my ListView to selected item of combobox below is my code
<ListView Name="myStudent" ItemsSource="{Binding CmbSelected,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Width="420" Height="150">
<ListView.View >
<GridView x:Name="grdStudentDetails">
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ElementName=cmbID,Path=SelectedItem.ID}" Width="30"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding ElementName=cmbID,Path =SelectedItem.Name}" Width="100"/>
<GridViewColumn Header="RollNum" DisplayMemberBinding="{Binding ElementName=cmbID,Path=SelectedItem.RollNum}" Width="100"/>
<GridViewColumn Header="Subject" DisplayMemberBinding="{Binding ElementName=cmbID,Path=SelectedItem.Sub}" Width="100"/>
<GridViewColumn Header="PhNumber" DisplayMemberBinding="{Binding ElementName=cmbID,Path=SelectedItem.PhNum}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
I am not able to find where I am doing mistake even I bind my text box with same binding it is working fine. please refer textbox just below my combobox's XAML.
my viewmodle.cs code is as follow
private student cmbSelcted;
public student CmbSelected
{
get { return cmbSelcted; }
set { cmbSelcted = value; OnPropertyChanged("CmbSelected"); }
}
public ObservableCollection<student> MyStudent
{
get { return myStudent; }
set { myStudent = value; OnPropertyChanged("MyStudent"); }
}
Can't see the ItemsSource of your ListView! Hope you've bind it to an collection. If not - try this approach.
<ListView Grid.Row="1" ItemsSource="{Binding SelectedStudents, Mode=OneWay}">
<ListView.View >
<GridView x:Name="grdStudentDetails">
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}" Width="30"/>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="100"/>
<GridViewColumn Header="RollNum" DisplayMemberBinding="{Binding RollNum}" Width="100"/>
<GridViewColumn Header="Subject" DisplayMemberBinding="{Binding Sub}" Width="100"/>
<GridViewColumn Header="PhNumber" DisplayMemberBinding="{Binding PhNum}" Width="100"/>
</GridView>
</ListView.View>
</ListView>
ViewModel
private Student _cmbSelected;
public Student CmbSelected
{
get { return _cmbSelected; }
set
{
_cmbSelected = value;
if (_cmbSelected != null)
{
SelectedStudents = new List<Student>() { _cmbSelected };
}
else
{
SelectedStudents = new List<Student>();
}
OnPropertyChanged();
}
}
private List<Student> _selectedStudents;
public List<Student> SelectedStudents
{
get { return _selectedStudents; }
set
{
_selectedStudents = value;
OnPropertyChanged();
}
}
Hope you see that it's important to have an ItemsSource on your ListView.
<Grid>
<StackPanel>
<ListView x:Name="usergrid" Margin="100,50,100,0" HorizontalAlignment="Center" FontSize="20" ItemsSource="{Binding Path=user1}">
<ListView.View>
<GridView>
<GridViewColumn Header="UserId" DisplayMemberBinding="{Binding UserId,Mode=TwoWay}" Width="100" ></GridViewColumn>
<GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName,Mode=TwoWay}" Width="150" />
<GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName,Mode=TwoWay}" Width="150" />
<GridViewColumn Header="City" DisplayMemberBinding="{Binding City,Mode=TwoWay}" Width="150" />
<GridViewColumn Header="State" DisplayMemberBinding="{Binding State,Mode=TwoWay}" Width="150" />
<GridViewColumn Header="Country" DisplayMemberBinding="{Binding Country,Mode=TwoWay}" Width="150" />
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</Grid>

Listview in Usercontrol in Flyout remains empty

I'm trying to place a usercontrol in a flyout window. In this usercontrol I'm trying to bind a list to a listview, but the listview remains empty.
C# UserControl
public MusicList()
{
InitializeComponent();
}
public void Makemusiclist(Inhabitant inhabitant, Wait wait, Rectangle rect)
{
musicList.Width = rect.Width;
musicList.Height = rect.Height;
lViewMusicFiles.Width = rect.Width - 150; // place the box on the right plce on any screen
lViewMusicFiles.Height = rect.Height - 50;
List<MusicFile> playlist = new List<MusicFile>(); // get the inhabitants' playlist from his file
playlist = inhabitant.musicList;
lViewMusicFiles.DataContext = playlist;
lViewMusicFiles.ItemsSource = playlist;
lViewMusicFiles.Items.Refresh();
musicList.UpdateLayout();
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
{
wait.Close();
}));
}
XAML Usercontrol
<Grid>
<ListView x:Name="lViewMusicFiles" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Red" Foreground="White" FontSize="32" Margin="150,50,0,0" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectionMode="Single" SelectionChanged="lViewMusicFiles_SelectionChanged" Style="{DynamicResource ListViewStyle1}" >
<ListView.View>
<GridView>
<GridViewColumn Header="Titel" Width="Auto" DisplayMemberBinding="{Binding Path=title}"/>
<GridViewColumn Header="Artist" Width="Auto" DisplayMemberBinding="{Binding Path=artist}"/>
<GridViewColumn Header="Album" Width="Auto" DisplayMemberBinding="{Binding Path=album}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</UserControl>
XAML flyout
<Grid>
<local:MusicList x:Name="musicList" />
</Grid>
Use ObservableCollection<T> instead of List<T>. you can write binding in XAML like this. I didn't write irrelevant properties.
<ListView x:Name="lViewMusicFiles" ItemsSource="{Binding Playlist, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}">
<ListView.View>
<GridView>
<GridViewColumn Header="Titel" DisplayMemberBinding="{Binding title}"/>
<GridViewColumn Header="Artist" DisplayMemberBinding="{Binding artist}"/>
<GridViewColumn Header="Album" DisplayMemberBinding="{Binding album}"/>
</GridView>
</ListView.View>
</ListView>
Also you need this property.
public ObservableCollection<MusicFile> Playlist{ get; } = new ObservableCollection<MusicFile>();

WPF - Filling a ListView

I have a 2 column ListView and I'm trying to fill it using and IDictionary with the following code.
System.Collections.IDictionary entryList = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
foreach (System.Collections.DictionaryEntry de in entryList)
{
Row row = new Row();
row.Name1 = (string)de.Key;
row.Name2 = (string)de.Value;
this.list1.Items.Add(row);
}
public class Row
{
public string Name1 { get; set; }
public string Name2 { get; set; }
}
XAML:
<ListView x:Name="varList"
Grid.ColumnSpan="1"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Height="400"
Width="500"
Margin="0, 30, 0, 0">
<ListView.View>
<GridView>
<GridViewColumn Width="150" Header="Name" />
<GridViewColumn Width="350" Header="Path" />
</GridView>
</ListView.View>
</ListView>
But every row and column gets filled with "Project.Views.Row".
Anyone got any idea on how to fix it? Thank you very much.
A ListView (and every other control for that matter) will display the results of calling ToString when given an object to display.
For a standard class, thats its qualified name; Project.Views.Row in your example.
There are two ways to fix this:
Don't add an object. Instead, format the string as you want it ie:
list1.Items.Add(String.Format({0}:{1}, row.Name1, row.Name2));
Do this the right way and use MVVM. In this case your XAML needs a data template:
<ListView ItemsSource="{Binding Rows}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name1}"/>
<TextBlock Text="{Binding Name2}"/>
</StackPanel>
</DataTemplate>
<ListView.ItemTemplate>
</ListView>
For a grid view:
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name1}" />
<GridViewColumn Header="Path" DisplayMemberBinding="{Binding Name2}"/>
</GridView>
</ListView.View>
Binding the ItemsSource is not actually necessary, but since we are doing everything the right way, you should do it so you are not directly manipulating the UI from code.

Categories