WPF ListView doesn't work - c#

I have been experiencing problems with WPF ListView (using elements binding), as I tried to initialize it by injecting ItemsSource the list of Disks, and got no visual feedback from the element. I wrote my code using the example supplied here.
Here are the relevant code parts:
Setting the ListView
private void viewDisk_Click(object sender, RoutedEventArgs e)
{
List<DiskDetails> data = new List<DiskDetails>();
foreach(Disk disk in disks)
data.Add(new DiskDetails(disk.GetVolumeHeader().DiskName, disk.GetVolumeHeader().DiskOwner,disk.GetVolumeHeader().ProdDate));
disksList.ItemsSource = data;
}
DiskDetails Class
public class DiskDetails
{
public string diskName { get; set; }
public string diskOwner { get; set; }
public string cDate { get; set; }
public DiskDetails(string dN, string dO,string cD)
{
diskName = dN;
diskOwner = dO;
cDate = cD;
}
}
WPF ListView
<Grid Grid.Column="0">
<ListView x:Name="disksList" VerticalAlignment="Top" Height="250" SelectionChanged="disksList_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="Disk Name" Width="108" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Disk Owner" Width="108" DisplayMemberBinding="{Binding Age}" />
<GridViewColumn Header="Creation Date" Width="108" DisplayMemberBinding="{Binding Mail}" />
</GridView>
</ListView.View>
</ListView>
<Button x:Name="viewDisk" Content="View Disk" Width="90" Height="40" VerticalAlignment="Bottom" Margin="0,0,0,15" Click="viewDisk_Click"/>
</Grid>
Thanks.

Looks like your DisplayMemberBinding wasn't changed from the example code. Try changing the bindings to match the properties of DiskDetails. E.g. DisplayMemberBinding="{Binding Name}" should change to DisplayMemberBinding="{Binding diskName}"

Related

How to display processes in listview WPF?

I need to display all processes, namely: Process name, ID, and priority in ListView
I tried:
public Process[] processes;
public string[] processesss;
public MainWindow() {
InitializeComponent();
processes = Process.GetProcesses();
ProcessInfo.ItemsSource = processes;
}
XAML:
<ListView Name="ProcessInfo">
<ListView.View>
<GridView>
<GridViewColumn Header="Process Name" Width="100" DisplayMemberBinding="{ProcessName}"/>
<GridViewColumn Header="Process ID" Width="100" DisplayMemberBinding="{ID}"/>
<GridViewColumn Header="Status" Width="70"/>
</GridView>
</ListView.View>
</ListView>
try this
InitializeComponent();
processes = Process.GetProcesses();
List<processlist> processlist = new List<processlist>();
foreach (Process item in processes)
{
processlist.Add(new processlist() { id = item.Id, name = item.ProcessName });
}
ProcessInfo.ItemsSource = processlist;
and add this class
public class processlist
{
public int id { get; set; }
public string name { get; set; }
}
WPF UI
<Grid >
<ListView Margin="10" Name="ProcessInfo">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding name}" />
<GridViewColumn Header="id" Width="50" DisplayMemberBinding="{Binding id}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
You're on the right track. Just make sure your UI element has got correct binding information to pick properties from the ItemsSource. Could be a bit easier for you if you replace ListView with a DataGrid and set its AutoGenerateColumns to True. This will automatically start showing your processes in the grid.
On the other hand, you can use ListView or even ListBox for your purpose, but then you'll have to set up ItemTemplate for your control, which is a broad topic in itself.

ListView with Dictionary

Hello I'm looking for a way to use listview with Dictionary.
public class ServiceDataObject : IEquatable<ServiceDataObject>
{
public int ServiceID { get; set; }
public string ServiceName { get; set; }
public bool Status { get; set; }
public string ReccomendedStatus { get; set; }
public string WhoMade { get; set; }
public bool Equals(ServiceDataObject other)
{
if (other == null) return false;
return (this.ServiceID.Equals(other.ServiceID));
}
}
public static Dictionary<int, ServiceDataObject> ServiceData = new Dictionary<int, ServiceDataObject>();
This is how my dictionary looks like.
lvUsers.ItemsSource = Order_CONTROLS.ServiceData;
This is how I assign data to listview
And lvUsers listview:
<ListView Margin="10" Name="lvUsers">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<RadioButton IsChecked="{Binding Status}" GroupName="{Binding ServiceName}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<local:InvertBooleanConverter x:Key="InvertBooleanConverter" />
</DataTemplate.Resources>
<RadioButton IsChecked="{Binding Status, Converter={StaticResource InvertBooleanConverter}}" GroupName="{Binding ServiceName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Reccomendation" Width="120" DisplayMemberBinding="{Binding ReccomendedStatus}" />
<GridViewColumn Header="Description" Width="50" DisplayMemberBinding="{Binding ServiceName}" />
</GridView>
</ListView.View>
Problem is that it does not print data to items only correct, only number of rows are correct, but no data output, can anyone tell what I did wrong and if possible without using LIST(T)?
The solution is to set Values Collection to ItemsSource of the ListView:
lvUsers.ItemsSource = Order_CONTROLS.ServiceData.Values;
Remember also that Dictionary isn't Observable -> INotifyCollectionChanged & INotifyPropertyChanged interfaces aren't implemented.
So if you add a new element to the dictionary, your view will not see this change.

ListView Binding to List of Custom class containing Dictionnary

I am learning WPF and I am trying to fill a ListView with a list of folders (as ListView Groups) and files for each folder(as ListView Items).
Using WPF/MVVM Quick Start Tutorial , I created the following classes (Business removed)
public class PatchGen
{
public PatchGen() { }
private string _folderName;
private Dictionary<string, string> _filesInfo = new Dictionary<string, string>();
public string FolderName
{
get { return _folderName; }
set { _folderName= value; }
}
public Dictionary<string, string> FilesInfo
{
get { return _filesInfo; }
set { _filesInfo = value; }
}
}
and the ViewModel:
public class PatchGenViewModel : ObservableObject
{
public PatchGenViewModel()
{
}
List<PatchGen> _folderList = new List<PatchGen>();
public List<PatchGen> Folders
{
get
{
return _folderList;
}
set { }
}
void AddFilesExecute()
{
//business here
}
bool CanAddFilesExecute()
{
return true;
}
public ICommand AddFiles { get { return new RelayCommand(AddFilesExecute, CanAddFilesExecute); } }
The xaml section includes the DataContextand the CollectionViewSource:
<Window.DataContext>
<local:PatchGenViewModel></local:PatchGenViewModel>
</Window.DataContext>
<Window.Resources>
<CollectionViewSource x:Key='groups'
Source="{Binding Path=Folders}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="FolderName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
and the ListView:
<ListView Grid.Row="1"
HorizontalAlignment="Stretch"
Name="lstViewServices"
ItemsSource='{Binding Source={StaticResource groups}}'>
<ListView.View>
<GridView>
<GridViewColumn Header="File Name"
DisplayMemberBinding="{Binding Path=??? }"
Width="100" />
<GridViewColumn Header="File Path"
DisplayMemberBinding="{Binding Path=??? }"
Width="Auto" />
</GridView>
</ListView.View>
</ListView>
The ListView Group is not showing the Folders Names. ?
How to have the File Name and the File Path that represents the FilesInfo (Dictionnary < string,string > ) information displayed?
Is there any way to do this through XAML and ViewModel Class without the Code behind of the Xaml file?
You need to just bind the File name to the File to the folder name property.
For the File Path, you need to bind it to the FilesInfo property. Why is it a dictionary? I guess I didn't understand why you are using a dictionary here? Maybe I am missing something but you should drop the dictionary and create your own little object.
public class FileInfo
{
public string FileName {get;set;}
public string FilePath {get;set;}
}
Then of course change your PatchGen object to use that instead of a Dictionary.
Maybe a screenshot of what you want it to look like would help. However, if you look at your XAML, you don't have anywhere to put your FolderName. You only have places for FileName and FilePath.
<ListView Grid.Row="1"
HorizontalAlignment="Stretch"
Name="lstViewServices"
ItemsSource='{Binding Source={StaticResource groups}}'>
<ListView.View>
<GridView>
<GridViewColumn Header="File Name"
DisplayMemberBinding="{Binding Path=FileName }"
Width="100" />
<GridViewColumn Header="File Path"
DisplayMemberBinding="{Binding Path=FilePath}"
Width="Auto" />
</GridView>
</ListView.View>
</ListView>
So you should add a place for FolderName. You have two lists it seems: the folder list and for each folder a the file list. But your view only has one level.
Here is an example that has two levels.
<ItemsControl ItemsSource='{Binding Folders}'>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding FolderName}" />
<ListView Grid.Row="1"
HorizontalAlignment="Stretch"
Name="lstViewServices"
ItemsSource="FileInfo">
<ListView.View>
<GridView>
<GridViewColumn Header="File Name"
DisplayMemberBinding="{Binding Path=FolderName}"
Width="100" />
<GridViewColumn Header="File Path"
DisplayMemberBinding="{Binding Path=FolderName }"
Width="Auto" />
</GridView>
</ListView.View>
</ListView>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

C# Threadpool creating UI Element

I am updating a listbox via databind and one of the columns I am trying to insert is a checkbox. This update is being processed by a threadpool and I am able to insert the data fine, except for the checkbox. When I create the checkbox its displaying the xaml instead of the checkbox element.
i.e.
System.Windows.Controls.Checkbox Content: IsChecked:False
Definition of NotesReminderViewDetails
private struct NotesRemindersViewDetails
{
public string NoteReminderID { get; set; }
public string NoteReminderEnterDate { get; set; }
public string NoteReminderDueDate { get; set; }
public string NoteReminderConents { get; set; }
public CheckBox NoteReminderCompleted { get; set; }
}
Here is the code I am using to update the listview. NoteReminderType is a struct with all the note/reminder information.
NoteReminderType noteType = noteReminder.NoteReminderDetails;
NotesRemindersViewDetails noteReminderDetails = new NotesRemindersViewDetails();
noteReminderDetails.NoteReminderID = noteType.UserFriendlyNoteReminderID.ToString();
noteReminderDetails.NoteReminderEnterDate = noteType.InsertionDate.ToShortDateString();
noteReminderDetails.NoteReminderDueDate = noteType.DueDate.ToShortDateString();
noteReminderDetails.NoteReminderConents = noteType.Description;
listViewNotesReminders.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate()
{
noteReminderDetails.NoteReminderCompleted = new CheckBox();
listViewNotesReminders.Items.Add(noteReminderDetails);
}));
What do I need to change to get the checkbox to be displayed instead of the xaml form the threadpool thread?
EDIT
Here is the xaml code for the listview
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="20" DisplayMemberBinding="{Binding Path=NoteReminderID}" />
<GridViewColumn Header="Entered Date" Width="Auto" DisplayMemberBinding="{Binding Path=NoteReminderEnterDate}" />
<GridViewColumn Header="Due Date" Width="75" DisplayMemberBinding="{Binding Path=NoteReminderDueDate}" />
<GridViewColumn Header="Note Contents" Width="300" DisplayMemberBinding="{Binding Path=NoteReminderConents}" />
<GridViewColumn Header="Completed" Width="Auto" DisplayMemberBinding="{Binding Path=NoteReminderCompleted}" />
</GridView>
</ListView.View>
Rather than putting a UI element (CheckBox) in the data for the ListView, you should define a template so you can render the column as a checkbox, and just use a Boolean for the data. Using a CheckBox in your data is mixing your UI and data layers.
Update:
Here's an example (not tested) of how to make a custom column template:
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="20"
DisplayMemberBinding="{Binding Path=NoteReminderID}" />
<GridViewColumn Header="Entered Date" Width="Auto"
DisplayMemberBinding="{Binding Path=NoteReminderEnterDate}" />
<GridViewColumn Header="Due Date" Width="75"
DisplayMemberBinding="{Binding Path=NoteReminderDueDate}" />
<GridViewColumn Header="Note Contents" Width="300"
DisplayMemberBinding="{Binding Path=NoteReminderConents}" />
<GridViewColumn Header="Completed" Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=NoteReminderCompleted}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
You need to use bool field for NoteReminderCompleted instead of CheckBox.

WPF Listview databinding to generic List, dynamically filled by WCF service

In WPF app I have a WCF service which dynamically fills a generic List object from a backend database.
How in this case (List created in runtime), I could bind List items to a ListView object items?
It is the Data contract for my Web service:
....
[DataContract]
public class MeetList
{
[DataMember]
public string MeetDate;
[DataMember]
public string MeetTime;
[DataMember]
public string MeetDescr;
.....
static internal List<MeetList> LoadMeetings(string dynamicsNavXml)
{
...// Loads XML stream into the WCF type
}
Here in this event handler I read the WCF service and Loop through a List object:
private void AllMeetings()
{
Customer_ServiceClient service = new Customer_ServiceClient();
foreach (MeetList meet in service.ReadMeetList())
{
?????? = meet.MeetDate; // it's here that I bumped into a problem
?????? = meet.MeetTime; //
?????? = meet.MeetDescr;//
}
}
My Listview XAML:
<Grid>
<ListView Height="100" Width="434" Margin="0,22,0,0" Name="lvItems" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" SelectionMode="Single">
<ListView.View>
<GridView>
<GridViewColumn Header="Date" Width="100" HeaderTemplate="{StaticResource DateHeader}" CellTemplate="{DynamicResource DateCell}"/>
<GridViewColumn Header="Time" Width="100" HeaderTemplate="{StaticResource TimeHeader}" CellTemplate="{DynamicResource TimeCell}"/>
<GridViewColumn Header="Description" Width="200" HeaderTemplate="{StaticResource DescriptionHeader}" CellTemplate="{DynamicResource DescriptionCell}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
And data templates for this ListView:
<Window.Resources>
<DataTemplate x:Key="DateHeader">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="10,0,0,0" Text="Date" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DateCell" DataType="Profile">
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<Binding Path="MeetDate" />
</TextBlock.Text>
</TextBlock>
</StackPanel>
</DataTemplate>
......
How in this case (List created in runtime), I could bind my generic List items to a ListView object items?
I tried to use lvItems.ItemsSource = profiles; , but it doesn't work in my event handler
List doesn't have behaviour to notify that items count is changed. You should use a list with support INotifyCollectionChanged.. for example: ObservableCollection<T>. ObservableCollection<T> will inform your lvItems that items count is changed and it will be properly display.
Using intermediate ObservableCollection:
ObservableCollection<Meets> _MeetCollection =
new ObservableCollection<Meets>();
public ObservableCollection<Meets> MeetCollection
{ get { return _MeetCollection; } }
public class Meets
{
public string Date { get; set; }
public string Time { get; set; }
public string Description { get; set; }
}
In the event handler loop we put:
private void AllMeetings()
{
Customer_ServiceClient service = new Customer_ServiceClient();
_MeetCollection.Clear();
foreach (MeetList meet in service.ReadMeetList())
{
_MeetCollection.Add(new Meets
{
Date = meet.MeetDate,
Time = meet.MeetTime,
Description = meet.MeetDescr
});
}
}
And XAML binding is changed to:
<Grid>
<ListView Height="100" Width="434" Margin="0,22,0,0" Name="lvItems" ItemsSource="{Binding MeetCollection}">
<ListView.View>
<GridView>
<GridViewColumn Header="Date" Width="100" DisplayMemberBinding="{Binding Date}"/>
<GridViewColumn Header="Time" Width="100" DisplayMemberBinding="{Binding Time}"/>
<GridViewColumn Header="Description" Width="200" DisplayMemberBinding="{Binding Description}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>

Categories