Left Alignement with wpf grid - silverlight

In a WP7.5 application, i have a listbox containing a grid.
This grid contain two row, and two columns (2x2)
In grid, i display textbox, my problem is thar the alignement is bad ! I don't know why, i set horizontalAligement=true, but no change !
Here is my code :
<ListBox x:Name="ListBoxTiers" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
<Grid Margin="20" VerticalAlignment="Top" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="0" Grid.Column="0" Margin="0,0,10,0" x:Name="TxtBox_cCodeTiers" Text="{Binding m_strCode}" FontWeight="Bold" FontSize="22" />
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="0" Grid.Column="1" Margin="0,0,10,0" x:Name="TxtBox_cNomTiers" Text="{Binding m_strNom}" FontWeight="Bold" FontSize="22" />
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" Margin="0,0,10,0" x:Name="TxtBox_cCPostal" Text="{Binding m_strFonction}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Here is my result :
Here is my Class :
public class CTiers
{
public enum TypeTiers { Client, Fournisseur, Contact, Collaborateur, Commercial, Prospect};
TypeTiers m_TypeTiers { set; get; }
public string m_strTypeTiers { get; set; }
public string m_strCode { set; get; }
public string m_strNom { set; get; }
public string m_strPrenom { set; get; }
public string m_strTel { set; get; }
public string m_strGsm { set; get; }
public string m_strFax { set; get; }
public string m_strMail { set; get; }
public string m_strWebSite { set; get; }
public string m_strVille { set; get; }
public string m_strCpostal { set; get; }
public string m_strRue { set; get; }
public string m_strFonction { set; get; }
public CTiers()
{
}
public CTiers(TypeTiers oTypeTiers, string strCode, string strNom, string strPrenom, string strTel, string strGsm, string strFax, string strRue,string strVille,string strCPostal,string strMail,string strWebSite,string strFonction)
{
m_TypeTiers = oTypeTiers;
m_strCode = strCode.Trim();
m_strNom = strNom.Trim();
m_strPrenom = strPrenom.Trim();
m_strVille = strVille.Trim();
m_strTel = strTel.Trim();
m_strGsm = strGsm.Trim();
m_strFax = strFax.Trim();
m_strWebSite = strWebSite.Trim();
m_strRue = strRue.Trim();
m_strMail = strMail.Trim();
m_strCpostal = strCPostal.Trim();
m_strTypeTiers = oTypeTiers.ToString().Trim();
m_strFonction = strFonction.Trim();
}
}
Anyone could help me please ?
Thanks a lot :)
Best regards

Your code is ok, problem is with the text trimming only.
I used the same xaml in your question and did a sample.
Case 1: First I took all the strings trimmed
List<Myclass> list = new List<Myclass>();
list.Add(new Myclass() { m_strCode = "001", m_strNom = "sample1", m_strFonction = "Fonction1" });
list.Add(new Myclass() { m_strCode = "002", m_strNom = "sample2", m_strFonction = "Fonction2" });
list.Add(new Myclass() { m_strCode = "003", m_strNom = "sample3 ", m_strFonction = "Fonction3" });
list.Add(new Myclass() { m_strCode = "004", m_strNom = "sample4", m_strFonction = "Fonction4" });
list.Add(new Myclass() { m_strCode = "005", m_strNom = "sample5", m_strFonction = "Fonction5" });
ListBoxTiers.ItemsSource = list;
And the result is : (Formated clearly as you expect)
Case 2: In this case, I took some strings with extraa spaces (observe sample1 and 004)
List<Myclass> list = new List<Myclass>();
list.Add(new Myclass() { m_strCode = "001", m_strNom = " sample1", m_strFonction = "Fonction1" });
list.Add(new Myclass() { m_strCode = "002", m_strNom = "sample2", m_strFonction = "Fonction2" });
list.Add(new Myclass() { m_strCode = "003", m_strNom = "sample3 ", m_strFonction = "Fonction3" });
list.Add(new Myclass() { m_strCode = "004 ", m_strNom = "sample4", m_strFonction = "Fonction4" });
list.Add(new Myclass() { m_strCode = "005", m_strNom = "sample5", m_strFonction = "Fonction5" });
ListBoxTiers.ItemsSource = list;
And now the result is :
Hence, the problem is you are not properly trimming the text. Take care about that.
Update:
There you go. You don't always call the constructor for instantiating the object. So, the better way is this.
private string _m_strFonction;
private string _m_strNom;
private string _m_strCode;
public string m_strCode
{
get { return _m_strCode; }
set { _m_strCode = value.Trim(); }
}
public string m_strNom
{
get { return _m_strNom; }
set { _m_strNom = value.Trim(); }
}
public string m_strFonction
{
get { return _m_strFonction; }
set { _m_strFonction = value.Trim(); }
}

You're probably better off with a ListView rather than a ListBox. However, if you must use a ListBox, then the issue you're seeing is because every data item has it's own Grid. In other words, they are not sharing the same Columns. To circumvent this, add a width to each of the column definitions:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
This will provide a common width for all the left columns and the right columns will all start at the same location as well. Assuming nothing in the left columns are wider than whatever is set as the Width.

I think that problem is with Margin in Grid and with text trimming.
Try with Margin set to "0, 20, 20, 20":
<ListBox x:Name="ListBoxTiers" ItemsSource="{Binding}"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
<Grid Margin="0, 20, 20, 20" VerticalAlignment="Top" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="0" Grid.Column="0" Margin="0,0,10,0" x:Name="TxtBox_cCodeTiers" Text="{Binding m_strCode}" FontWeight="Bold" FontSize="22" Loaded="TxtBlock_Loaded" />
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="0" Grid.Column="1" Margin="0,0,10,0" x:Name="TxtBox_cNomTiers" Text="{Binding m_strNom}" FontWeight="Bold" FontSize="22" Loaded="TxtBlock_Loaded" />
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" Margin="0,0,10,0" x:Name="TxtBox_cCPostal" Text="{Binding m_strFonction}" Loaded="TxtBlock_Loaded" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Trim text to improve alignment:
private void TxtBlock_Loaded(object sender, RoutedEventArgs e)
{
TextBlock tb = sender as TextBlock;
tb.Text = tb.Text.Trim();
}
If column contains data with constant width you can specify it in XAML:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

Related

How to get datacontext of an event emitting item control?

I have a bunch of buttons being render inside an items control. I want to get access to the data context of the clicked button. How can I achieve that?
Model:
public class RunYear
{
public RunYear(int year)
{
Year = year;
Months = new Month[3];
}
public int Year { get; set; }
public Month[] Months { get; set; }
}
public class Month
{
public int ColumnIndex { get; set; }
public string MonthName { get; set; }
// some other props
}
Code behind:
public partial class MainWindow : Window
{
private ObservableCollection<RunYear> _years = new ObservableCollection<RunYear>();
public ObservableCollection<RunYear> Years { get{return _years; } }
public MainWindow()
{
DataContext = this;
InitializeComponent();
GenerateData();
}
private void GenerateData()
{
for (int i = 2010; i < 2015; i++)
{
var runYear = new RunYear(i);
runYear.Months[0] = new Month() { ColumnIndex = 0, MonthName = $"Jan {i}" };
runYear.Months[1] = new Month() { ColumnIndex = 1, MonthName = $"Feb {i}" };
runYear.Months[2] = new Month() { ColumnIndex = 2, MonthName = $"Mar {i}" };
Years.Add(runYear);
}
}
public void OnClick(object sender, RoutedEventArgs args)
{
// how do I get the databound item?
var cp = sender as ContentPresenter; //doesn't work
var vm = cp?.Content as Month;
}
}
XAML:
<Grid>
<ItemsControl Name="icYears" ItemsSource="{Binding Years}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="75"/>
</Grid.RowDefinitions>
<DockPanel Grid.Column="0" Grid.Row="0" >
<TextBox IsReadOnly="True" TextAlignment="Center" Text="{Binding Year}" />
</DockPanel>
<ItemsControl Grid.Column="1" Name="icMonths" ItemsSource="{Binding Months}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="75"></RowDefinition>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column" Value="{Binding ColumnIndex}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Click="OnClick" Content="{Binding MonthName}" Padding="2" Margin="2"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Do you mean like this?
private void Button_Click(object sender, RoutedEventArgs e)
{
var vm = (sender as FrameworkElement).DataContext;

WPF Control losing focus when clicking on a tab

On a tabcontrol I have several tabpages, on one of the tabs there is a textbox in the content.
This textbox is content bound with a simple Path=PropertyName and UpdateSourceTrigger=LostFocus. The reason I am using LostFocus is I trap the Lost focus event of the Textbox and possibly reformat the text. This is a "time" textbox and if they enter "0900", I want to reformat to "09:00". This part works great when I press the tab key to move to the next control, but if I type "0900" then press one of the other tabs, I hit the lost focus and re-format the value in the textbox, BUT the bind never gets called to update my object. When I come back to the tab, the value is blanked out (or reset to the original value on the object)
Any ideas why textbox does not trigger the Binding update when changing tab page?
Note: this also happens with a regular textbox that does wire to the lost focus event. It seems to have something to do with click on the tab.
[[Added Code ]]
More notes:
1. I am dynamically creating the tabs and controls on the tab (not sure if that has something to do with it or not)
2. I am using the Prism libraries
MainWindow Xaml
<Window.Resources>
<DataTemplate DataType="{x:Type ctrls:myTextBoxDef}">
<Grid Width="300">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Text="{Binding LabelText}" />
<TextBox Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Text="{Binding DocValue,
Mode=TwoWay,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=LostFocus}"
/>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
IsTabStop="False"
ItemsSource="{Binding Tabs, Mode=OneWay}"
SelectedItem="{Binding SelectedTab,
Mode=TwoWay,
NotifyOnSourceUpdated=True}"
>
<TabControl.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Margin="18,14,22,0"
Text="{Binding HeaderText}" />
</Grid>
</DataTemplate>
</TabControl.ItemTemplate>
<!-- Content -->
<TabControl.ContentTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<AdornerDecorator Grid.Column="0">
<ItemsControl Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsTabStop="False"
ItemsSource="{Binding Controls,
Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Grid.Column="0"
Margin="10,5,0,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</AdornerDecorator>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
Main Window Code Behind
public partial class MainWindow : Window
{
private DataContextObject obj = new DataContextObject();
public MainWindow()
{
InitializeComponent();
myTextBoxDef txt1 = new myTextBoxDef(obj, "Textbox 1", "TAB1TextBox1");
myTextBoxDef txt1b = new myTextBoxDef(obj, "Textbox 1 value", "TAB1TextBox1");
myTextBoxDef txt2 = new myTextBoxDef(obj, "Textbox 2", "TAB1TextBox2");
myTextBoxDef txt2b = new myTextBoxDef(obj, "Textbox 2 value", "TAB1TextBox2");
obj.Tabs.Add(new myTabDef("Tab 1", new ObservableCollection<myTextBoxDef>() { txt1, txt2 }));
obj.Tabs.Add(new myTabDef("Tab 2", new ObservableCollection<myTextBoxDef>() { txt1b, txt2b }));
obj.SelectedTab = obj.Tabs[0];
this.DataContext = obj;
}
}
Supporting objects
public class DataContextObject : NotificationObject
{
List<myTabDef> _tabs = new List<myTabDef>();
public List<myTabDef> Tabs
{
get
{
return _tabs;
}
}
private myTabDef _item;
public myTabDef SelectedTab
{
get
{ return _item; }
set
{
_item = value;
this.RaisePropertyChanged("SelectedItem");
}
}
private string _txt1 = "";
public string TAB1TextBox1
{
get { return _txt1; }
set
{
_txt1 = value;
this.RaisePropertyChanged("TAB1TextBox1");
}
}
private string _txt2 = "";
public string TAB1TextBox2
{
get { return _txt2; }
set
{
_txt2 = value;
this.RaisePropertyChanged("TAB1TextBox2");
}
}
private string _txt3 = "";
public string TAB2TextBox1
{
get { return _txt3; }
set
{
_txt3 = value;
this.RaisePropertyChanged("TAB2TextBox1");
}
}
}
public class myTabDef
{
public myTabDef(string tabText, ObservableCollection<myTextBoxDef> controls)
{
HeaderText = tabText;
_left = controls;
}
public string HeaderText { get; set; }
private ObservableCollection<myTextBoxDef> _left = new ObservableCollection<myTextBoxDef>();
public ObservableCollection<myTextBoxDef> Controls
{
get
{
return _left;
}
}
}
public class myTextBoxDef : NotificationObject
{
public myTextBoxDef(NotificationObject bound, string label, string bindingPath)
{
LabelText = label;
Path = bindingPath;
BoundObject = bound;
BoundObject.PropertyChanged += BoundObject_PropertyChanged;
}
public string LabelText
{
get;
set;
}
public NotificationObject BoundObject
{
get;
set;
}
public string DocValue
{
get
{
return PropInfo.GetValue(BoundObject, null) as string;
}
set
{
PropInfo.SetValue(BoundObject, value, null);
}
}
protected virtual void BoundObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(Path))
{
this.RaisePropertyChanged("DocValue");
}
}
public string Path
{
get;
set;
}
private PropertyInfo pi = null;
protected PropertyInfo PropInfo
{
get
{
if (pi == null && BoundObject != null && !string.IsNullOrEmpty(Path))
{
PropertyInfo[] properties = BoundObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
pi = properties.Where((prop) => string.Compare(prop.Name, Path, true) == 0).FirstOrDefault();
}
return pi;
}
}
}
We have found a solution. I came cross this set of postings
https://groups.google.com/forum/#!topic/wpf-disciples/HKUU61A5l74
They talk about a control called TabControlEx. Towards the bottom (5th from the bottom) you will see a posting by Sacha Barber that has a zip file with an example.
It solved all our problems we were having.
here is also another link where the code for the Class is posted
http://updatecontrols.codeplex.com/discussions/214434

Databinding issue in windows phone

Hi I am trying to study the data binding property in windows phone. I googled and got some blogs. As learned from those blogs I binded values in a ListBox. Now the listbox showng many products with name, amount , date, image properties. But now I am trying to do this, if click on any product in the list I want to navigate to other page and display the product details there. But in that page the databinding is not working. Just those textblocks shows nothing. I included my code below. Please help me to find the problem in my code.
Transaction.cs
public class Transaction
{
public String Name { get; set; }
public String Date { get; set; }
public int Amount { get; set; }
public String Type { get; set; }
public Transaction(String name, String date, int amount,String type)
{
this.Name = name;
this.Date = date;
this.Amount = amount;
this.Type = type;
}
}
public class ShowItem
{
public String SelectedItemName { get; set; }
public String SelectedItemImage { get; set; }
public String SelectedItemDate { get; set; }
public String SelectedItemAmount { get; set; }
public ShowItem(String name, String date, String amount, String image)
{
this.SelectedItemName = name;
this.SelectedItemDate = date;
this.SelectedItemAmount = amount;
this.SelectedItemImage = image;
}
}
MainPage.xaml
<Grid Height="530" Grid.Row="1" VerticalAlignment="Top" Margin="0,30,0,0">
<ListBox Margin="0,0,0,0" Name="TransactionList">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Width="460" Height="150" BorderThickness="0" Click="user_click" Name="rowButton" Background="{Binding Color}" >
<Button.Content>
<StackPanel Orientation="Horizontal" Height="auto" Width="400">
<Image Width="80" Height="80" Source="{Binding Type}"></Image>
<StackPanel Orientation="Vertical" Height="150" Margin="20,0,0,0">
<StackPanel Orientation="Horizontal" Height="40">
<TextBlock Width="100" FontSize="22" Text="Name :" Height="40" ></TextBlock>
<TextBlock Width="auto" FontSize="22" Text="{Binding Name}" Height="40" ></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="40">
<TextBlock Width="100" FontSize="22" Text="Date :" Height="40" ></TextBlock>
<TextBlock Width="100" FontSize="22" Text="{Binding Date}" Height="40" ></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="40">
<TextBlock Width="100" FontSize="22" Text="Amount :" Height="40" ></TextBlock>
<TextBlock Width="auto" FontSize="22" Text="{Binding Amount}" Height="40" ></TextBlock>
<TextBlock Width="auto" FontSize="22" Text=" $" Height="40" ></TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
MainPage.xaml.cs
public partial class MainPage : PhoneApplicationPage
{
string[] _dates = { "19/9/1984", "25/8/1952", "27/5/1992", "4/8/1975", "10/3/2000", "22/1/2002", "23/5/2012", "25/9/1963", "13/7/1999", "15/4/1936" };
string[] _imageList = { "69290979.png", "acrobat-reader-cs-4.png","azureus-1.png","ClothDolls_lnx-Icons-Colored_Blue_Doll_256x256.png-256x256.png","database-27.png",
"documents-folder-2.png", "Front_Row_Icon.png","gear-8.png","info-chat.png","itunes-6.png","nero-smart-start-1.png",
"network-2.png","picasa.png","quicktime-7-red.png","twitter-bird.png","wlm-1.png" };
string[] _items = { "Television", "Radio", "Fridge", "Fan", "Light", "Cup", "Plate", "Dress", "Laptop", "Mobile" };
int[] _prices = { 10, 15, 20, 25, 30, 5, 8, 15, 10, 20 };
List<Transaction> transactionList;
// Constructor
public MainPage()
{
InitializeComponent();
Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
int count = 50;
String DefaultName = "";
String DefaultDate = "";
int DefaultAmount = 0;
String DefaultImage = "";
transactionList = new List<Transaction>();
Random random = new Random();
for (int i = 0; i < _items.Length; i++)
{
DefaultName = _items[i];
DefaultDate = _dates[i];
DefaultAmount = _prices[i];
DefaultImage = "Images/" + _imageList[random.Next(0, _imageList.Length)];
transactionList.Add(new Transaction(DefaultName, DefaultDate, DefaultAmount, DefaultImage));
}
TransactionList.ItemsSource = transactionList;
}
private void user_click(object sender, RoutedEventArgs e)
{
var myData = ((Button)sender).DataContext as Transaction;
NavigationService.Navigate(new Uri("/DisplayProduct.xaml?Name=" + myData.Name +"&Date=" + myData.Date + "&Amount=" + myData.Amount + "&Type=" + myData.Type, UriKind.Relative));
}
}
DisplayProduct.xaml
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Orientation="Vertical">
<StackPanel HorizontalAlignment="Center">
<Image Width="auto" Height="auto" Name="itemImage" Source="{Binding SelectedItemImage}"></Image>
</StackPanel>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" Width="350" HorizontalAlignment="Left">
<StackPanel Orientation="Horizontal" Margin="0,20,0,0">
<TextBlock Text="Name : " Width="150" Height="70" FontSize="35" Foreground="DarkSalmon"></TextBlock>
<TextBlock Name="itemName" Text="{Binding SelectedItemName}" Width="auto" Height="70" FontSize="35"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,20,0,0">
<TextBlock Text="Amount : " Width="150" Height="70" FontSize="35" Foreground="DarkSalmon"></TextBlock>
<TextBlock Name="itemPrice" Text="{Binding SelectedItemAmount}" Width="auto" Height="70" FontSize="35"></TextBlock>
<TextBlock Name="currency" Text="$" Width="auto" Height="70" FontSize="35"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,20,0,0">
<TextBlock Text="Date : " Width="150" Height="70" FontSize="35" Foreground="DarkSalmon"></TextBlock>
<TextBlock Name="itemDate" Text="{Binding SelectedItemDate}" Width="auto" Height="70" FontSize="35"></TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
DisplayProduct.xaml.cs
public partial class DisplayProduct : PhoneApplicationPage
{
public DisplayProduct()
{
InitializeComponent();
Loaded += new RoutedEventHandler(DisplayProduct_Loaded);
}
void DisplayProduct_Loaded(object sender, RoutedEventArgs e)
{
string name = NavigationContext.QueryString["Name"];
string date = NavigationContext.QueryString["Date"];
string amount = NavigationContext.QueryString["Amount"];
string type = NavigationContext.QueryString["Type"];
ShowItem showItemClass = new ShowItem(name, date, amount, type);
}
}
void DisplayProduct_Loaded(object sender, RoutedEventArgs e)
{
string name = NavigationContext.QueryString["Name"];
string date = NavigationContext.QueryString["Date"];
string amount = NavigationContext.QueryString["Amount"];
string type = NavigationContext.QueryString["Type"];
ShowItem showItemClass = new ShowItem(name, date, amount, type);
DataContext = showItemClass;
}
You forgot to set the DataContext of the page. It doesn't know where should it get data to display.

Bind nested listview from ViewModel in WPF

I am beginner in WPF. I am trying bind nested listview from ViewModel.
I have two listview parent and child respectively. In my parent listview datatemplate want bind child listview it's something
like nested gridview in asp.net. Could any one there please help me to sort out this problem.
Data Display like:
StudentID Name
S101 Azad
Math 3
C# 3
Here StudentID,Name parent listview content and subjects are child listview content which is filter by StudentID.
Thanks,
Az#d
<Grid>
<ListView ItemsSource="{Binding Students}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="2"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0"/>
<TextBlock Text="{Binding RollNo}" Grid.Column="2"/>
<ListView ItemsSource="{Binding SubjectAndMarks}" Grid.Row="2" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Subject}" Grid.Column="0"/>
<TextBlock Text="{Binding Marks}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
public class SubjectAndMarks
{
public string Subject { get; set; }
public double Marks { get; set; }
}
public class Student
{
public string Name { get; set; }
public int RollNo { get; set; }
public ObservableCollection<SubjectAndMarks> SubjectAndMarks { get; set; }
}
public class ViewModel //ViewModel
{
public ObservableCollection<Student> Students { get; set; }
public ViewModel()
{
Students = new ObservableCollection<Student>();
Students.Add(new Student()
{
Name = "Harish",
RollNo = 1,
SubjectAndMarks = new ObservableCollection<SubjectAndMarks>()
{new SubjectAndMarks(){Subject="Maths",Marks=100},new SubjectAndMarks(){Subject="Hindi",Marks=100},
new SubjectAndMarks(){Subject="Science",Marks=100}}
});
Students.Add(new Student()
{
Name = "Pankaj",
RollNo = 2,
SubjectAndMarks = new ObservableCollection<SubjectAndMarks>()
{new SubjectAndMarks(){Subject="Maths",Marks=100},new SubjectAndMarks(){Subject="Hindi",Marks=40},
new SubjectAndMarks(){Subject="Science",Marks=30}}
});
Students.Add(new Student()
{
Name = "Deepak",
RollNo = 3,
SubjectAndMarks = new ObservableCollection<SubjectAndMarks>()
{new SubjectAndMarks(){Subject="Maths",Marks=90},new SubjectAndMarks(){Subject="Hindi",Marks=50},
new SubjectAndMarks(){Subject="Science",Marks=60}}
});
}
}
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
I hope that will help.

ListBox binding with ViewModel in WPF

I am new to the WPF and trying to build a sample application using the MVVM framework. My application has a xaml file which has some textboxes for inputing customer info, combo box for display of states and a save button. All the databinding is done through ViewModel(CustomerViewMode) which has a reference to the Model(Customer), containing the required fields and their
Getter, setters. The viewModel has a CustomerList property.
On clicking the save button, I want to display the FirstName and LastName properties of Customer in a ListBox. This is where the problem is. I debugged the code,
(Click event of button in the code behind), I can see that the CustomerList has the first Customer object with all its details, but its not getting displayed in the listbox.
My code is:
Customer(Model);
enter code here
namespace SampleMVVM.Models
{
class Customer : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private String _firstName;
private String _lastName;
private Address _customerAddress;
public String FirstName
{
get { return _firstName; }
set
{
if (value != _firstName)
{
_firstName = value;
RaisePropertyChanged("FirstName");
}
}
}
public String LastName
{
get { return _lastName; }
set
{
if (value != _lastName)
{
_lastName = value;
RaisePropertyChanged("LastName");
}
}
}
public Address CustomerAddress
{
get { return _customerAddress; }
set
{
if (value != _customerAddress)
{
_customerAddress = value;
RaisePropertyChanged("CustomerAddress");
}
}
}
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Address(Model)
namespace SampleMVVM.Models
{
class Address : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _addressLine1;
private string _addressLine2;
private string _city;
//private string _selectedState;
private string _postalCode;
private string _country;
public String AddressLine1
{
get { return _addressLine1; }
set
{
if (value != _addressLine1)
{
_addressLine1 = value;
RaisePropertyChanged(AddressLine1);
}
}
}
public String AddressLine2
{
get { return _addressLine2; }
set
{
if (value != _addressLine2)
{
_addressLine2 = value;
RaisePropertyChanged(AddressLine2);
}
}
}
public String City
{
get { return _city; }
set
{
if (value != _city)
{
_city = value;
RaisePropertyChanged(City);
}
}
}
public String PostalCode
{
get { return _postalCode; }
set
{
if (value != _postalCode)
{
_postalCode = value;
RaisePropertyChanged(PostalCode);
}
}
}
public String Country
{
get { return _country; }
set
{
if (value != _country)
{
_country = value;
RaisePropertyChanged(Country);
}
}
}
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
CustomerViewModel:
namespace SampleMVVM.ViewModels
{
class CustomerViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Customer _customer;
RelayCommand _saveCommand;
private List<String> _stateList = new List<string>();
private string _selectedState;
private ObservableCollection<Customer> _customerList = new ObservableCollection<Customer>();
//public CustomerViewModel(ObservableCollection<Customer> customers)
//{
// _customers = new ListCollectionView(customers);
//}
public Customer CustomerModel
{
get { return _customer; }
set
{
if (value != _customer)
{
_customer = value;
RaisePropertyChanged("CustomerModel");
}
}
}
public List<String> StateList
{
get
{
return _stateList;
}
set { _stateList = value; }
}
public ObservableCollection<Customer> CustomerList
{
get
{
return _customerList;
}
set
{
if (value != _customerList)
{
_customerList = value;
RaisePropertyChanged("CustomerList");
}
}
}
public CustomerViewModel()
{
CustomerModel = new Customer
{
FirstName = "Fred",
LastName = "Anders",
CustomerAddress = new Address
{
AddressLine1 = "Northeastern University",
AddressLine2 = "360, Huntington Avenue",
City = "Boston",
PostalCode = "02115",
Country = "US",
}
};
StateList = new List<String>
{
"Alaska", "Arizona", "California", "Connecticut", "Massachusetts", "New Jersey", "Pennsylvania", "Texas"
};
SelectedState = StateList.FirstOrDefault();
}
public String SelectedState
{
get { return _selectedState; }
set
{
if (value != _selectedState)
{
_selectedState = value;
RaisePropertyChanged(SelectedState);
}
}
}
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
CustomerInfo.xaml(view)
<UserControl x:Class="SampleMVVM.Views.CustomerInfo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ViewModels="clr-namespace:SampleMVVM.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<ViewModels:CustomerViewModel />
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<!--Starting label-->
<TextBlock FontSize="18" FontFamily="Comic Sans MS" FontWeight="ExtraBlack"
Foreground="Navy"
Grid.Row="0" HorizontalAlignment="Center">
<TextBlock.Text>
Customer Information:
</TextBlock.Text>
</TextBlock>
<TextBlock Text="First name: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="1" Width="80px" Height="50px" Margin="40,5,0,0"/>
<TextBox Text="{Binding CustomerModel.FirstName}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="1" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0" Name="fname"/>
<TextBlock Text="Last Name: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="2" Width="80px" Height="50px" Margin="40,5,0,0"/>
<TextBox Text="{Binding CustomerModel.LastName}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="2" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0" Name="lname"/>
<TextBlock Text="Address: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="3" Width="80px" Height="50px" Margin="40,5,0,0"/>
<TextBox Text="{Binding CustomerModel.CustomerAddress.AddressLine1}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="3" Grid.Column="1" Width="160px" Height="20px" Margin="20,5,0,0"/>
<TextBox Text="{Binding CustomerModel.CustomerAddress.AddressLine2}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="4" Grid.Column="1" Width="160px" Height="30px" Margin="20,5,0,0"/>
<TextBlock Text="City: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="5" Width="80px" Height="20px" Margin="40,5,0,0"/>
<TextBox Text="{Binding CustomerModel.CustomerAddress.City}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="5" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"/>
<TextBlock Text="State: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="6" Width="80px" Height="20px" Margin="40,5,0,0"/>
<ComboBox Grid.RowSpan="2" HorizontalAlignment="Left" Name="listOfSates"
VerticalAlignment="Top"
Grid.Row="6" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"
ItemsSource="{Binding Path=StateList}"
SelectedItem="{Binding Path=SelectedState}"
SelectionChanged="ComboBox_SelectionChanged"
>
</ComboBox>
<TextBlock Text="PostalCode: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="7" Width="80px" Height="20px" Margin="40,5,0,0"/>
<TextBox Text="{Binding CustomerModel.CustomerAddress.PostalCode}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="7" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"/>
<TextBlock Text="Country: " Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="8" Width="80px" Height="20px" Margin="40,5,0,0"/>
<TextBox Text="{Binding CustomerModel.CustomerAddress.Country}" Grid.RowSpan="2" HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="8" Grid.Column="1" Width="80px" Height="20px" Margin="20,5,0,0"/>
<Button Content="Save" Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="9" Width="50px" Height="20px" Name="savebtn" Margin="40,5,0,0"
Click="savebtn_Click"/>
<ListBox Name="cList" ItemsSource="{Binding Path=CustomerList}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Grid.Row="1" Grid.Column="2" Grid.RowSpan="2" Width="200px" Height="300px" Margin="200,5,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding CustomerModel.FirstName}"
FontWeight="Bold" Foreground="Navy"/>
<TextBlock Text=", " />
<TextBlock Text="{Binding CustomerModel.LastName}"
FontWeight="Bold" Foreground="Navy"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
CustomerInfo(Code behind class)
namespace SampleMVVM.Views
{
/// <summary>
/// Interaction logic for CustomerInfo.xaml
/// </summary>
public partial class CustomerInfo : UserControl
{
public CustomerInfo()
{
InitializeComponent();
//checkvalue();
}
private void savebtn_Click(object sender, RoutedEventArgs e)
{
////Customer c = new Customer();
////c.FirstName = fname.Text;
////c.LastName = lname.Text;
//CustomerViewModel cvm = new CustomerViewModel();
//cvm.CustomerModel.FirstName = fname.Text;
//cvm.CustomerModel.LastName = lname.Text;
//List<CustomerViewModel> customerList = new List<CustomerViewModel>();
//customerList.Add(cvm);
var viewModel = DataContext as CustomerViewModel;
if (viewModel != null)
{
//viewModel.ShowCustomerInfo();
String strfname = viewModel.CustomerModel.FirstName;
String strname = viewModel.CustomerModel.LastName;
viewModel.CustomerList.Add(viewModel.CustomerModel);
String str1 = viewModel.CustomerList.FirstOrDefault().FirstName;
int i = viewModel.CustomerList.Count();
//cList.ItemsSource = viewModel.CustomerList;
}
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
CustomerViewModel cvm = new CustomerViewModel();
cvm.SelectedState = listOfSates.SelectedItem.ToString();
}
}
}
I just cant understand where am I going wrong...Someone please help
And for the correct binding in ListBox.ItemTemplate:
<TextBlock Text="{Binding FirstName}"
FontWeight="Bold" Foreground="Navy"/>
<TextBlock Text="{Binding LastName}"
FontWeight="Bold" Foreground="Navy"/>
The DataContext of ListBoxItem is a Customer already.
You only create a new instance of a CustomerModel object once in your code (in the Customer View Model constructor). So you are constantly updating the same customer object rather than creating a new one.
At the end of your click handler you should do a
viewModel.CustomerModel = new Customer();
HOWEVER
Rather than having a click handler you should have an ICommand in your view model for adding a new customer. Then you should bind to command of your button to the ICommand in your view model.
you were binding the CustomerLIst.FirstName which is not walid because innterconent will check for property name customerlist in side the listbox itemssource. and as its not their then it will raise a silent error but wo't show into GUI, what you need to do is just provide the propertyname like firstname and lastname that will work.
well besides your binding in listbox every thing else is ok. just replace you listbox binding as like below.
<TextBlock Grid.Row="0"
Grid.Column="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="List of Customers" />
<ListBox Name="cList"
Grid.Row="1"
Grid.RowSpan="8"
Grid.Column="2"
ItemsSource="{Binding CustomerList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontWeight="Bold"
Foreground="Black"
Text="{Binding FirstName}" />
<TextBlock Text=", " />
<TextBlock FontWeight="Bold"
Foreground="Black"
Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Grid.Row="10"
Grid.Column="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding CustomerList.Count,
StringFormat='Total Customers, ={0}'}" />
better to take command insteed of events.
Your problem is in this line of code:
RaisePropertyChanged("CustomerList");
It doesn't work for collection add/remove events. Take a look at ObservableCollection and Item PropertyChanged.
Keep in mind that in MVVM, you should not have much code (if any) in code behind. Consider using commands.

Resources