Bind Combox inside a ListView - c#

I have created a ListView with a ComboBox
<ListView x:Name="lstvAttendance" Margin="0,53,0,10">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="0" DisplayMemberBinding="{Binding Path=Id}"/>
<GridViewColumn Header="Emp Code" Width="100" DisplayMemberBinding="{Binding Path=emp_id}"/>
<GridViewColumn Header="Employee Name" Width="160" DisplayMemberBinding="{Binding Path=name}"/>
<GridViewColumn Header="Status" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox x:Name="cmbStatus" Width="75" Text="{Binding Path=status}" SelectedItem="{Binding Path=status}">
<ComboBoxItem Content="P"/>
<ComboBoxItem Content="A"/>
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Date" Width="135">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DatePicker x:Name="dtpDate" Width="120" Text="{Binding attendance_date}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Reg Date" Width="140" DisplayMemberBinding="{Binding Path=reg_date}"/>
<GridViewColumn Header="Last Update" Width="140" DisplayMemberBinding="{Binding Path=last_update}"/>
<GridViewColumn Header="Delete" Width="70">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btnRemove" Content="Remove" Width="60" BorderThickness="0" CommandParameter="{Binding}" HorizontalContentAlignment="Right" Style="{StaticResource DelImg}" Cursor="Hand" Foreground="Blue"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
I need to Bind this ComboBox(ComboBox has either P or A).For Binding these ListView from DataBase I created a class Attendance.
public class Attendance
{
public string Id { get; set; }
public string emp_id { get; set; }
public string name { get; set; }
public string status { get; set; } //Either P or A
public string attendance_date { get; set; }
public string reg_date { get; set; }
public string last_update { get; set; }
}
And then:
try
{
using (SqlConnection con = new SqlConnection(DBCon.conStr))
{
con.Open();
using (SqlCommand cmd = new SqlCommand(AppConstraints.LIST_VIEW_ATTENDANCE))
{
cmd.Connection = con;
cmd.CommandType = CommandType.StoredProcedure;
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
lstvAttendance.Items.Add(new Attendance()
{
Id = dr["Id"].ToString(),
emp_id = dr["emp_id"].ToString(),
name = dr["name"].ToString(),
attendance_datedr["attendance_date"].ToString(),
status = dr["status"].ToString(),
reg_date = dr["reg_date"].ToString(),
last_update = dr["last_update"].ToString()
});
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
My code works for other fields in ListView. But ComboBox value not select. I need help to select ComboBox value with respect to Database value.

Firstly:Create a List of Attendance instead of adding items to lstvAttendance and then set the lstvAttendance's ItemsSource like this:
List<Attendance> lst = new List<Attendance>();
try
{
....
....
while (dr.Read())
{
lst.Add(new Attendance()
{
....
}
}
...
...
lstvAttendance.ItemsSource = lst;
}
catch
{
....
}
Secondly: You missed the ItemsSource property of your ComboBox it should be like this:
<ComboBox x:Name="cmbStatus" Width="75" DisplayMemberPath="status"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=ListView}, Path=ItemsSource}"
SelectedValuePath="status" SelectedValue="{Binding Path=status}">
</ComboBox>

You should use SelectedValuePath binding then bind to the SelectedValue=status property of viewModel.
Binding to SelectedItem will always contain the actually selected item ( ComboBoxItem) not the actual value.
<ComboBox x:Name="cmbStatus" Width="75" SelectedValuePath="{Binding Path=Content}" SelectedValue="{Binding Path=status}">
<ComboBoxItem Content="P"/>
<ComboBoxItem Content="A"/>
</ComboBox>

Related

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.

WPF ListView doesn't work

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

WPF ListView Column of Text Some Rows Underlined Some Not

I need to display databound data in a listview such that some of the cells of the same column are underlined while others are not:
How do I create a data template that will display different control types in the same cell? (Visual Studio 2013, .NET 4.5.2)
XAML:
<ListView Grid.Column="3" ItemsSource="{Binding Results.MyItemSource, Mode=OneWay}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="Auto" Header=" " DisplayMemberBinding="{Binding Path=Caption, Mode=OneWay}"/>
<GridViewColumn Width="Auto" Header=" " DisplayMemberBinding="{Binding Path=Value, Mode=OneWay}" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
ItemSource:
public List<object> MyItemSource
{
get
{
return new List<object>
{
new CaptionValuePair {Caption = "Caption1", Value = new TextBlock {Text = "Value1"}},
new CaptionValuePair {Caption = "Caption2", Value = new TextBlock {Text = "Value2", TextDecorations = TextDecorations.Underline}}
};
}
}
Bound type:
public class CaptionValuePair
{
public string Caption { get; set; }
public object Value { get; set; }
}
Problem: The StackPanel is just displaying the typename of a textblock.
Instead of a StackPanel, using an ItemsControl and binding its ItemsSource property worked.
XAML:
<GridViewColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Path=Value, Mode=OneWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
Bound type:
public List<UIElement> Value{ get; set; }

C# How to check all checkboxes on listview

How to check all checkboxes on listview?
Listview xaml:
<ListView x:Name="List" HorizontalAlignment="Left" Height="559" Margin="10,10,0,0" VerticalAlignment="Top" Width="607" Grid.ColumnSpan="2" ScrollViewer.HorizontalScrollBarVisibility="Visible" ScrollViewer.VerticalScrollBarVisibility="Auto" IsMouseCapturedChanged="List_IsMouseCapturedChanged">
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Name="Dodaj" Header="Dodaj" Click="DodajUtwor_Click"/>
<MenuItem Name="Usuń" Header="Usuń Zaznaczone" Click="UsuńUtwór_Click"/>
<MenuItem Name="Clear" Header="Wyczyść Listę" Click="ClearList_Click"/>
<MenuItem Name="Check" Header="Zaznacz Wszystkie" Click="SelectAll_Click"/>
</ContextMenu>
</ListView.ContextMenu>
<ListView.View>
<GridView>
<GridViewColumn Width="30" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBox" Padding="10" IsChecked="{Binding IsChecked}"/>
<TextBlock Text="{Binding Data}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Nazwa Pliku" Width="100" DisplayMemberBinding="{Binding Nazwa}" />
<GridViewColumn Header="Tytuł" Width="100" DisplayMemberBinding="{Binding Tytuł}"/>
<GridViewColumn Header="Wykonawca" Width="100" DisplayMemberBinding="{Binding Autor}"/>
<GridViewColumn Header="Album" Width="100" DisplayMemberBinding="{Binding Album}"/>
<GridViewColumn Header="Nr" Width="100" DisplayMemberBinding="{Binding Nr}"/>
<GridViewColumn Header="Rok" Width="100" DisplayMemberBinding="{Binding Rok}"/>
<GridViewColumn Header="Gatunek" Width="100" DisplayMemberBinding="{Binding Gatunek}"/>
<GridViewColumn Header="Komantarze" Width="100" DisplayMemberBinding="{Binding Komentarze}"/>
<GridViewColumn Header="Okładka" Width="100" DisplayMemberBinding="{Binding Okładka}"/>
<GridViewColumn Header="Lokalizacja" Width="100" DisplayMemberBinding="{Binding Lokalizacja}"/>
</GridView>
</ListView.View>
</ListView>
Code:
private void Button_Click(object sender, RoutedEventArgs e)
{
MyItem selectedItem = (MyItem)this.List.SelectedItem;
selectedItem.IsChedked = true;
List.Items.Refresh();
}
Don't work.
I want to change all checkboxes on true in a listviev. I dont know how to use loop foreach. And how to delete items witch checkboxes on true?
I guess you might be looking for a checkbox in the header column and select all grid items when header checkbox got selected.
We can do this having simple child/sub viewmodels. Below code might help/solve your problem.
Xaml/View code -
<GridViewDataColumn DataMemberBinding="{Binding IsChecked}" >
<GridViewDataColumn.Header >
<CheckBox HorizontalAlignment="Left" IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewDataControl}}
,Path=DataContext.CheckAll}"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewDataControl}}
,Path=DataContext.CheckAllCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=IsChecked}" />
</GridViewDataColumn.Header>
<GridViewDataColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="CheckBox" Padding="10" IsChecked="{Binding IsChecked}" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewDataControl}}
,Path=DataContext.ItemCommand}" CommandParameter="{Binding}"/>
<TextBlock Text=y"{Binding Data}"/>
</StackPanel>
</DataTemplate>
</GridViewDataColumn.CellTemplate>
</GridViewDataColumn>
and you can have your view models as explained below.
class MainViewModel : Common.UserInterface.ViewModelBase, IDisposable
{
public MainViewModel()
{
CheckAllCommand = new DelegateCommand<bool>(OnCheckAllExecuted);
}
void OnCheckAllExecuted(bool status)
{
// Your logic goes here (if any)
CheckAll = items.All(item => item.IsChecked);
}
public DelegateCommand<ItemViewModel> ItemCommand { get; private set; }
private bool checkAll;
private ObservableCollection<ItemViewModel> items;
public DelegateCommand<bool> CheckAllCommand
{
get;
private set;
}
public ObservableCollection<ItemViewModel> Items
{
get
{
return items;
}
set
{
items = value;
OnPropertyChanged(() => Items);
}
}
public bool CheckAll
{
get { return checkAll; }
set
{
checkAll = value;
OnPropertyChanged(() => CheckAll);
}
}
}
class ItemViewModel : ViewModelBase
{
public bool ischecked;
public string data;
public new bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
OnPropertyChanged("IsChecked");
}
}
public string Data
{
get { return data; }
set
{
data = value;
OnPropertyChanged("Data");
}
}
}

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