How can i bind data in ListViewItem? - wpf

I have a ListView with some Columns. One of Column contains two RadioButton.When i checked Radiobutton,i want change the binding value of the last column(it's header Name is Fee).I have no idea,can someone help me ?
<ListView x:Name="lvTimeView">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="ID" Width="175" DisplayMemberBinding="{Binding serverId}"></GridViewColumn>
<GridViewColumn Header="IP" Width="175" DisplayMemberBinding="{Binding serverIp}"></GridViewColumn>
<GridViewColumn x:Name="gvcTime" Header="Time" Width="400">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="30">
<RadioButton x:Name="rbOneMonth" Tag="1" Checked="rbChecked" Style="{StaticResource BoxRadioButton}" HorizontalAlignment="Left">OneMonth</RadioButton>
<RadioButton x:Name="rbTwoMonth" Tag="2" Margin="8,0,0,0" Checked="rbChecked" Style="{StaticResource BoxRadioButton}" HorizontalAlignment="Left">TwoMonth</RadioButton>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Fee" Width="100" DisplayMemberBinding="{Binding fee}">
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>

First, forget about events in this example. This is a perfect example to leverage WPF binding...
Change your XAML to this.
<ListView ItemsSource="{Binding Items}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="ID" Width="175" DisplayMemberBinding="{Binding ServerId}"></GridViewColumn>
<GridViewColumn Header="IP" Width="175" DisplayMemberBinding="{Binding ServerIp}"></GridViewColumn>
<GridViewColumn Header="Time">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<RadioButton GroupName="{Binding ServerId}" IsChecked="{Binding OneMonth}">OneMonth</RadioButton>
<RadioButton GroupName="{Binding ServerId}" IsChecked="{Binding TwoMonth}" Margin="5,0,0,0">TwoMonth</RadioButton>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Fee" Width="100" DisplayMemberBinding="{Binding Fee}">
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Pay attention to RadioButtons GroupName property. This is just so the radio buttons know they are a part of a radio button group so when you select one the other one unselects. We have to set this to something unique per row so I chose serverId. I hope this is unique in your case otherwise you will have to generate some Guid or something...
Next is the model...
public class Item : INotifyPropertyChanged
{
private string _serverId;
private string _serverIp;
private bool _oneMonth;
private bool _twoMonth;
private decimal _fee;
public event PropertyChangedEventHandler PropertyChanged;
public string ServerId
{
get => _serverId;
set
{
_serverId = value;
OnPropertyChanged(nameof(ServerId));
}
}
public string ServerIp
{
get => _serverIp;
set
{
_serverIp = value;
OnPropertyChanged(nameof(ServerIp));
}
}
public bool OneMonth
{
get => _oneMonth;
set
{
_oneMonth = value;
if(value)
Fee = 100;
OnPropertyChanged(nameof(OneMonth));
}
}
public bool TwoMonth
{
get => _twoMonth;
set
{
_twoMonth = value;
if(value)
Fee = 200;
OnPropertyChanged(nameof(TwoMonth));
}
}
public decimal Fee
{
get => _fee;
set
{
_fee = value;
OnPropertyChanged(nameof(Fee));
}
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Instantiate the model and add it to the data context...
public partial class MainWindow : Window
{
public IEnumerable<Item> Items => new Item[]
{
new Item { ServerId = "asia", ServerIp = "10.1.1.45" },
new Item { ServerId = "europe", ServerIp = "45.1.4.211" },
new Item { ServerId = "australia", ServerIp = "37.2.1.181" }
};
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
}

Related

WPF combine icon and text in Listview with columns

I'm coding simple file explorer in WPF and I have Listview with 5 columns (Name, Extension, Size, Date, Attributes)
XAML looks this:
<ListView Name="ListView" BorderThickness="2,0,2,0" BorderBrush="Gray" Height="Auto" Width="Auto" >
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="450"/>
<GridViewColumn Header="Extension" DisplayMemberBinding="{Binding Extension}" Width="70"/>
<GridViewColumn Header="Size" DisplayMemberBinding="{Binding Size}" Width="80"/>
<GridViewColumn Header="Date" DisplayMemberBinding="{Binding Date}" Width="80"/>
<GridViewColumn Header="Attributes" DisplayMemberBinding="{Binding Attributes}" Width="60"/>
</GridView>
</ListView.View>
Then, I have class FileInfo with five properties, each binded to column via DisplayMemberBinding
public class FileInfo
{
public string Name { get; set; }
public string Extension { get; set; }
public string Size { get; set; }
public string Date { get; set; }
public string Attributes { get; set; }
}
var files = new List<FileInfo> { new FileInfo { Name = "Foo", Extension = ".sub", Date = "1.1.2015", Size = "3.05", Attributes = "H" } } //just as test
ListView.ItemsSource = files;
That works fine.
Now, in column Name I want to combine file name with its associated icon. And I don't know, how to do that. I don't want to create another column for icon, icon must be included in Name column.
Any ideas? Is there a way to do this programmatically, or do I need to modify XAML?
You need to create CellTemplate for your GridViewColumn like this
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="450">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="<Your Image Source>"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

Bind a custom class of controls to Listview/GridView as ListViewItem

I am facing some problem with binding the data to the controls in ListView/GridView as ListViweItem.
Requirement: Have to show a checkbox, Label, DropDown and a textbox per row which get data from all different sources.Here is the sample class:
class Data {
public CheckBox chk_box;
public Label lbl;
public ComboBox cmb_box;
public TextBox t_box;
public Data(String lbl_Data,List<String> cmb_box_Data) {
chk_box=new CheckBox();
lbl=new Label();
lbl.Content=lbl_Data;
cmb_box=new ComboBox();
cmb_box.ItemsSource=cmb_box_Data;
chk_box.Click += new RoutedEventHandler(chk_box_clicked);
...
}
private void chk_box_clicked(object Sender, RoutedEventArgs e){
if(chk_box.IsChecked == true) cmb_box.IsEnabled = false;
else cmb_box.IsEnabled = true;
}
}
Now i need to add this class' object as a ListViewItem, per control per column in ListView/GridView - dynamically, row by row and then after user makes selections access all the rows once again row by row and get values from these controls.
XAML code:
<ListView x:Name="TestGrid">
<ListView.View>
<GridView>
<GridViewColumn Header=" Select "/>
<GridViewColumn Header=" Label "/>
<GridViewColumn Header=" cmb_box "/>
<GridViewColumn Header=" t_box "/>
</GridView>
</ListView.View>
</ListView>
Since, the Items Source for all the controls is different, i cannot use ListView.ItemsSorce to bind data. Please suggest suitable options, or ways to accomplish the desired UI. I would like to make everything out from the controls given in VS only without using a third party dll(if possible).
Thank you for your time and suggestions in advance.
Check msdn.microsoft.com for binding
public class Datum
{
public bool Select { get; set; }
public string Name { get; set; }
public List<string> Items { get; set; }
}
<ListView ItemsSource="{Binding}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Select">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=Select, Mode=OneWay}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name, Mode= OneWay}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=Items}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>

Change ListViewItem text color

I am currently creating ListViewItems programatically like so:
ListView.Items.Add(New With {Key .Name = ItemName, Key .DateCreated = ItemDateCreated, Key .Description = ItemDescription})
I have found no way of changing the color of the item, as I have not found a way of creating a ListViewItem with sub items in any other way than this one.
Is it possible to change the color of the item's text (or background if not possible), while still being able to have subitems?
EDIT - This is my XAML:
<ListView x:Name="ListView" Opacity="0.75">
<ListView.View>
<GridView x:Name="ListViewGridView">
<GridViewColumn Header="Name" Width="155" DisplayMemberBinding="{Binding Path=Name}"/>
<GridViewColumn Header="Date Created" Width="150" DisplayMemberBinding="{Binding Path=DateCreated}"/>
<GridViewColumn Header="Description" Width="250" DisplayMemberBinding="{Binding Path=Description}"/>
</GridView>
</ListView.View>
</ListView>
The following sample will set the first column's text to green. On a side note, you should probably wrap your "Name", "Date Created" and "Description" fields into an actual object and use it to create your ListViewItem with subitems instead of trying to create a new weakly typed object each time (I did this and attached the code if you are interested, obviously you can use any data type for members (not just string) but I was coding quickly).
Information on DataTemplates:
http://msdn.microsoft.com/en-us/library/system.windows.datatemplate(v=vs.110).aspx
XAML:
<ListView x:Name="ListView" Opacity="0.75">
<ListView.View>
<GridView x:Name="ListViewGridView">
<GridViewColumn Header="Name" Width="155">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Color}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Date Created" Width="150" DisplayMemberBinding="{Binding Path=DateCreated}"/>
<GridViewColumn Header="Description" Width="250" DisplayMemberBinding="{Binding Path=Description}"/>
</GridView>
</ListView.View>
</ListView>
C#:
// In method somewhere, won't work otherwise
ListView.Items.Add(new DataClass("Bob", "12/04/2013", "Person", Color.Green));
public class DataClass
{
public String Name { get; set; }
public String DateCreated { get; set; }
public String Description { get; set; }
public SolidBrushColor { get; set; }
public DataClass (string Name, String Date, String Desc, SolidBrushColor textColor)
{
this.Name = Name;
this.DateCreated = Date;
Description = Desc;
Color = textColor;
}
}

How to set SelectedItem in listview control?

I have UserControl(AllCustomerView) in project and its Viewmodel as ALlCustomerViewModel consists a property as SearchText.
SearchText is selected value for TextBox inside a listview in UserControl.
SearchItem is set as customerViewmdel for SearchText.
But in listview , SearchItem is not set as selected
in AllCustomerView.xaml
<TextBlock>
<TextBox
Width="150"
Text="{Binding Path=SearchText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
</TextBox>
<Button
Command="{Binding Path=SearchCommand}"
Content=" Search ">
</Button>
</TextBlock>
<ListView
SelectedValue="{Binding Path=SearchText}"
ItemsSource="{Binding Path=AllCustomers}"
FontFamily="Tahoma"
FontSize="14"
ItemContainerStyle="{StaticResource CustomerItemStyle}"
IsSynchronizedWithCurrentItem="True">
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button
Command="{Binding ElementName=Root, Path=DataContext.DeleteCommand}"
Content="x"
FontFamily="Tahoma"
FontSize="10"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button
FontFamily="Tahoma"
FontSize="10"
Content="Edit"
Command="{Binding Path=DataContext.Editcommand,ElementName=Root}"
/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="CustomerID"
Width="130"
DisplayMemberBinding="{Binding Path=CustomerID}"/>
<GridViewColumn
Header="Contact Name"
Width="130"
DisplayMemberBinding="{Binding Path=ContactName}"/>
<GridViewColumn
Header="Company Name"
Width="130"
DisplayMemberBinding="{Binding Path=CompanyName}"/>
<GridViewColumn
Width="130"
Header="Contact Name"
DisplayMemberBinding="{Binding Path=ContactTitle}"
/>
</GridView>
</ListView.View>
</ListView>
and its viewmodel(AllcustomerViewModel.cs)
public ICommand SearchCommand
{
get
{
if (_search == null)
_search = new Relaycommand(SearchCustomer);
return _search;
}
}
public void SearchCustomer(object o)
{
System.Windows.Forms.MessageBox.Show(SearchItem.ToString());
}
public string searchText;
public string SearchText
{
get { return searchText; }
set
{
searchText = value;
var customerExsits = AllCustomers.Where(q => q.CustomerID.Trim().Equals(searchText));
if (customerExsits.Any())
{
SearchItem = customerExsits.Single();
}
}
}
public CustomerViewModel SearchItem
{
get;
set;
}
what should i set in SelectedValue in ListView, whether to set Customerviewmodel(as SelectedItem) or to set CustomerID(as SearchText)?
You should do the following:
Use this binding in your ListView: SelectedItem="{Binding Path=SearchItem }". Don't use SelectedValue.
Implement INotifyPropertyChanged in your ViewModel and raise the PropertyChanged event in the setter of the SearchItem property. Obviously, you need to change this property from an automatic one to a classical one with a backing field:
public CustomerViewModel SearchItem
{
get { return _searchItem; }
set
{
if(value == _searchItem)
return;
_searchItem = value;
RaisePropertyChanged("SearchItem");
}
}

WPF: Progress bar in ListView

I'm trying to display information from my ObservableCollection<MyData> in a ListView. MyData has:
string Name
string Location
int Progress
Using DataBinding, I'm able to display the Name and Location for all the items in my ObservableCollection<MyData> in their own column. But how can I add a Progress column with a ProgressBar inside? Progress is a percentage.
<ListView ItemsSource="{Binding PersonList}">
<ListView.View>
<GridView>
<GridViewColumn Width="140" Header="GameName" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Width="140" Header="Progress">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ProgressBar Maximum="100" Value="{Binding Progress}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Your ListView in XAML:
<ListView x:Name="DataView">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding Path=Name}" />
<ProgressBar Height="20" Width="100" Value="{Binding Path=Progress}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Code-behind:
internal class MyData
{
public string Name { get; set; }
public int Progress { get; set; }
}
...
var items = new ObservableCollection<MyData>();
items.Add(new MyData() { Name = "Some", Progress = 25 });
items.Add(new MyData() { Name = "Another", Progress = 91 });
DataView.ItemsSource = items;
Just bind Progress property in MyData to the ProgressBar.Value and set the expected MAX value as the ProgressBar.Maximum for example 50 below
<ProgressBar Maximum="50" Value="{Binding Progress}" ..

Resources