WPF User Control - wpf

I want to have a User Control that takes a collection of People (property "Data") and displays them in a list box.
When I run my app nothing shows in the listbox. Can you please point out what I'm doing wrong?
Thanks!!!
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return Name + "(" + Age + ")";
}
}
User Control:
(uc1.xaml.cs)
public partial class uc1
{
public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof (List<Person>), typeof (uc1));
public List<Person> Data
{
get { return (List<Person>) GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public uc1()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
DataContext = Data;
}
}
(uc1.xaml)
<ListBox ItemsSource="{Binding Name}" />

The ItemsSource property controls the list of items that are displayed in the listbox. If you want the ListBox to display one line for each person, you need to set the ItemsSource to bind directly to the DataContext. Then you use the DisplayMemberPath property to control which property of the Person class to show.
Here's my sample code that works for me.
The person class is the same.
The Window1.xaml.cs:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
List<Person> Data = new List<Person>();
Data.Add(new Person { Name = "Test 1", Age = 5 });
Data.Add(new Person { Name = "Test 2", Age = 10 });
this.DataContext = Data;
}
}
The Window1.xaml
<ListBox ItemsSource="{Binding}" DisplayMemberPath="Name" />

Related

Add a space in column header while binding ObservableCollection to a Grid

I want to add a space in my column header when I am binding my ObservableCollection to a Grid in MVVM way. Here is my code..
public class Site
{
public string Name { get; set; }
public string Description { get; set; }
[Description("Short Code")]
[Bindable(true)]
public string ShortCode { get; set; }
public static ObservableCollection<Site> GetSampleData()
{
var sites = new ObservableCollection<Site>();
sites.Add(new Site { Name = "New Delhi", Description = "New Delhi Railway Station", ShortCode = "NDLS"});
sites.Add(new Site { Name = "Mumbai", Description = "Mumbai Railway Station", ShortCode = "MUM"});
return sites;
}
}
// Here is my View Model Class
public class SiteViewModel
{
public ObservableCollection<Site> SitesDataCollection { get; set; }
public SiteViewModel()
{
SitesDataCollection = Site.GetSampleData();
}
}
// This is the View Class
public partial class SiteView : UserControl
{
public Sites()
{
InitializeComponent();
DataContext = new SiteViewModel();
}
}
My XAML is
<Grid>
<DockPanel>
<DataGrid Name="SiteGrid" ItemsSource="{Binding Path=SitesDataCollection}">
</DataGrid>
</DockPanel>
</Grid>
Basically in my Grid, for the third column , the header is ShortCode, I want to display "Short Code", How can I do that.
I tried adding
[Description("Short Code")] and
[Bindable(true)]
but didn't got the desired result.
In the AutoGeneratingColumn event handler of the DataGrid, access the DataGridColumn properties by referencing the DataGridAutoGeneratingColumnEventArgs.Column property. Use this to edit the column header.
private void DataGrid_OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column.Header = Regex.Replace(e.Column.Header.ToString(), "(\\B[A-Z])", " $1");
}
This will add spaces into your property names where there are upper case letters.

WPF ComboBox Binding : MVVM

I am trying to bind WPF combobox ItemsSource with a collection using MVVM design pattern. following is my code
XAML:
<ComboBox Height="30" Width="200" ItemsSource="{Binding PeopleList,Mode=TwoWay}"></ComboBox>
<TextBlock Height="Auto" Width="Auto" Text="{Binding SelectedPerson.ContactNo}"></TextBlock>
Code Behind :
public MainWindow()
{
InitializeComponent();
ViewModel vm = new ViewModel();
DataContext = vm;
}
Model Class :
class People : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set
{
name = value;
NotifyPropertyChanged("Name");
}
}
private string contactNo;
public string ContactNo
{
get { return contactNo; }
set
{
contactNo = value;
NotifyPropertyChanged("ContactNo");
}
}
private ObservableCollection<People> peopleList;
public ObservableCollection<People> PeopleList
{
get { return peopleList; }
set
{
peopleList = value;
NotifyPropertyChanged("PeopleList");
}
}
private People selectedPerson;
public People SelectedPerson
{
get { return selectedPerson; }
set
{
selectedPerson = value;
NotifyPropertyChanged("SelectedPerson");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
ViewModel Class :
class ViewModel
{
ObservableCollection<People> PeopleList = null;
public ViewModel()
{
PeopleList = new ObservableCollection<People>();
People p1 = new People { Name = "Naresh", ContactNo = "9574733355" };
People p2 = new People { Name = "Ritesh", ContactNo = "9099028779" };
People p3 = new People { Name = "Saumya", ContactNo = "9904848779" };
PeopleList.Add(p1);
PeopleList.Add(p2);
PeopleList.Add(p3);
People People = new People();
People.PeopleList = PeopleList;
}
So, this is what I have done so far. Here, the issue I am facing is when I click on combo box nothing is happening.
Thanks for your help in advance.
The PeopleList needs to be real property (not a local field):
public ObservableCollection<People> PeopleList { get; set; }
You have to replace the field entry
ObservableCollection<People> PeopleList = null;
by a property entry
public ObservableCollection<People> PeopleList { get; set; }
Only properties can be binded not fields.
Furthermore you should set the DisplayMemberPath to show more than the type name "People". The three items cannot be distinguished. You could show the names of the people
<ComboBox Height="30" Width="200" ItemsSource="{Binding PeopleList,Mode=TwoWay}" DisplayMemberPath="Name"></ComboBox>

WPF binding static list to combobox

Trying to understand how to bind this static list to a combobox that located on different window.
public partial class MainWindow : Window
{
public static List<Classes.Entity> EntityList { get; set; }
public MainWindow()
{
EntityList = new List<Classes.Entity>();
InitializeComponent();
}
...
the object:
public class Entity
{
public string entityName { get; set; }
...
XAML (In a diffrent window, call "NewRelationship.xaml.cs"
<ComboBox x:Name="cb_from" ItemsSource="{Binding Path=EntityList}" DisplayMemberPath="entityName" SelectedValue="{Binding Path=Entity}" />
Of course I fill the list later in the code...
if I moving the list to the newRelationship window and add "this.datacontext = this;" its working,
How do I make this work when the list is in the mainWindow? Thanks...
A better approach would be to keep the EntityList in a separate object that both windows could reference:
class ViewModel
{
private List<Classes.Entity> _entityList = new List<Classes.Entity>();
public IEnumerable<Classes.Entity> EntityList
{
get { return _entityList; }
}
}
partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
When the second window is created, you can pass an instance of the ViewModel class to it, and set it as the DataContext.

How to bind a textbox.Text property in WPF MMVM design

So I'm trying to learn the MVVM design patter in WPF, I want to do the following:
In external class I've got a ObservableCollection _students that is bound to a listview on the WPF window using MVVM design pattern. The listview shows only the Student's name and Age.
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Course { get; set; }
public DateTime JoiningDate { get; set; }
}
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Student> _students;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged!=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public ObservableCollection<Student> Students
{
get
{
return _students;
}
set
{
_students = value;
NotifyPropertyChanged("Students");
}
}
All good, but I want to put a TextBox and set it to show the listview's selected item's course property. This means I must
get the listview's selected index (ok)
bind the textbox.Text property to Students[that index].Course
I'm stuck at 2. Any help?
i would solve this by another way.
Take a look at this post
.
Another way would be that your ViewModel contains a Student-property(e.g. SelectedStudent) which is bind to the SelctedItem of the listView. Then you can handel this by
{Binding Path=SelectedStudent.Course}
Assume you bind the listview to a collection of type SampleData like below:
SampleData.cs
public class SampleData
{
public int Id { get; set; }
public string Text { get; set; }
public decimal Value { get; set; }
}
Then you bind the ListView ItemsSource to a collection. WIt does not matter if you bind ItemsSource property to a property on ViewModel or you bind it in code-behind like the code below.
var source = new List<SampleData>();
source.Add(new SampleData() { Id = 1, Text = "AAA" });
source.Add(new SampleData() { Id = 2, Text = "BBB" });
source.Add(new SampleData() { Id = 3, Text = "CCC" });
source.Add(new SampleData() { Id = 4, Text = "DDD" });
source.Add(new SampleData() { Id = 5, Text = "EEE" });
You can bind TextBox's Text property to the SelectedItem directly on the View.
<StackPanel Orientation="Horizontal">
<ListView x:Name="listView1" />
<TextBox Text="{Binding ElementName=listView1, Path=SelectedItem.Text}" />
</StackPanel>

Simple Windows Phone User Control Databinding Does Not Work

I have an issue with something that should be very simple databinding scenario. I want to bind a list of items. I want to create a user control put it in a ItemsControl's template and bind the ItemsControl to some data. I am perfectly happy with one time databinding so I was kind of hoping to avoid learning about dependency properties and all the databinding stuff for this simple scenario.
Here is the XAML for the user control:
<TextBlock>Just Something</TextBlock>
And the code behind:
namespace TestWindowsPhoneApplication
{
public partial class TestControl : UserControl
{
public TestData SomeProperty { get; set; }
public String SomeStringProperty { get; set; }
public TestControl()
{
InitializeComponent();
}
}
}
MainPage.xaml:
<ItemsControl Name="itemsList" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<t:TestControl SomeStringProperty="{Binding Path=SomeString}"></t:TestControl>
<!--<TextBlock Text="{Binding Path=SomeString}"></TextBlock>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here is MainPage.xaml.cs:
namespace TestWindowsPhoneApplication
{
public class TestData
{
public string SomeString { get; set; }
}
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
itemsList.DataContext = new TestData[] { new TestData { SomeString = "Test1" }, new TestData { SomeString = "Test2" } };
}
}
}
When I run the project I get an error "the parameter is incorrect". I also tried binding directly to the item with SomeProperty={Binding} since that is what I actually want to do but this causes the same error. If I try doing the same thing with the TextBlock control (the commented line) everything works fine.
How can I implement this simple scenario?
To make a property on your custom control "bindable" you have to make it a dependency property. Check out my answer here for a nice simple example of doing just this on a custom control: passing a gridview selected item value to a different ViewModel of different Usercontrol
public string SomeString
{
get { return (string)GetValue(SomeStringProperty); }
set { SetValue(SomeStringProperty, value); }
}
public static readonly DependencyProperty SomeStringProperty =
DependencyProperty.Register("SomeString", typeof(string), typeof(TestControl),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnSomeStringChanged)));
private static void OnSomeStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((TestControl)d).OnSomeStringChanged(e);
}
protected virtual void OnSomeStringChanged(DependencyPropertyChangedEventArgs e)
{
//here you can do whatever you'd like with the updated value of SomeString
string updatedSomeStringValue = e.NewValue;
}

Resources