Accessing contact data in Windows Phone 8 - c#

I have gone through msdn article "Accessing contact and calendar data for Windows Phone"
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh286414(v=vs.105).aspx#BKMK_CreatingtheApplicationProject
<TextBlock Text="phone numbers" Margin="12,12,0,0"/>
<ListBox ItemsSource="{Binding Path=PhoneNumbers}" Height="60" Margin="36,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=Kind, Mode=OneWay}" />
<TextBlock Grid.Column="1" Text=": " />
<TextBlock x:Name="pno" Grid.Column="2" Text="{Binding Path=PhoneNumber, Mode=OneWay}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In the above XAML Phone Number is dynamic bound to the TextBlock Name="pno"(Named myself not in msdn code)
I want to get the Phone number in a variable say Phone_no .How ????

Don't bind to the default ContactPhoneNumber (don't use the IEnumerable called PhoneNumbers for binding).
Create your own class to hold phone number data
public class MyContactPhoneNumber
{
public PhoneNumber Phone_no {get; set;}
//other properties you want
}
and create a new collection of those custom contact phone numbers
List<MyContactPhoneNumber> myNumbers = new List<MyContactPhoneNumber>();
Then in a foreach loop copy data from PhoneNumbers to a list of MyContactPhoneNumber
foreach (var number in PhoneNumbers)
myNumbers.Add(new MyContactPhoneNumber
{
//...copy all properties here, for example Phone_no = number.PhoneNumber
});
And then bind that to the UI
ListOfNumbers.ItemsSource = myNumbers;
// and in XAML
<ListBox Name="ListOfNumbers" Height="60" Margin="36,0,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="pno" Text="{Binding Path=Phone_no, Mode=OneWay}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you want two way binding support and better binding support overall, use ObservableCollection instead of a List and implement INotifyPropertyChanged in MyContactPhoneNumber class.

Related

Change type of control based on type of item source?

I am working with MVVM design pattern where I want to change the type of control to be used based on the type of item source object.
My code for item source types :
public class PropertyItemVM : ViewModelBase
{
// Some base code for all basic property items
}
public class StringValuePropertyItemVM : PropertyItemVM
{
// Code to correctly create string value property item
}
public class ComboBoxPropertyItemVM : PropertyItemVM
{
// Code to correctly create combo box property item
}
In my view model I have property list binded to xaml as
public ObservableCollection<PropertyItemVM> Properties { get; set; }
This collection contains both the types of objects StringValuePropertyItemVM and ComboBoxPropertyItemVM.
Now what I want to achieve is, based on type of object I want to decide whether the xaml will contain a TextBox or a ComboBox.
My xaml code :
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
With some help I found out I can have different data templates for both types and switch among those, however I can't find how to do that. Can anyone help me with how can this be achieved ?
Automatic Data Template Selection
Move the data templates to the ItemsControl resources and assign a DataType.
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:StringValuePropertyItemVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ComboBoxPropertyItemVM}">
<ComboBox/>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</StackPanel>
The ItemsControl will automatically select the right data template based on the type.
Data Template Selector
Although you do not need it in this case, for more complex cases (e.g. conditions based on the view model), you could implement a DataTemplateSelector, like this:
public class PropertyDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (!(container is FrameworkElement frameworkElement))
return null;
switch (item)
{
case StringValuePropertyItemVM _:
return (DataTemplate)frameworkElement.FindResource("StringValuePropertyItemVMDataTemplate");
case ComboBoxPropertyItemVM _:
return (DataTemplate)frameworkElement.FindResource("ComboBoxPropertyItemVMDataTemplate");
default:
return null;
}
}
}
Then you would define the data templates in a resource dictionary in scope with keys.
<DataTemplate x:Key="StringValuePropertyItemVMDataTemplate" DataType="{x:Type local:StringValuePropertyItemVM}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Content="{Binding Label}"
IsEnabled="{Binding IsEnabled}"
Grid.Column="0"/>
<!-- Here based on type need to change the TextBox with ComboBox-->
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="1"
IsEnabled="{Binding IsEnabled}"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="ComboBoxPropertyItemVMDataTemplate" DataType="{x:Type local:ComboBoxPropertyItemVM}">
<ComboBox/>
</DataTemplate>
Finally, you would assign or reference an instance of the selector to the ItemsControl.
<StackPanel>
<!--Items Control containing all list of properties to be shown-->
<ItemsControl x:Name="Local" ItemsSource="{Binding Properties}" Background="White">
<ItemsControl.ItemTemplateSelector>
<local:PropertyDataTemplateSelector/>
</ItemsControl.ItemTemplateSelector>
</ItemsControl>
</StackPanel>

Wpf Listbox doesn't bind to multiple items

the Xaml looks like this:
<ListBox Name="lbEurInsuredType" HorizontalContentAlignment="Stretch" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="30"></ColumnDefinition>
<!-- <ColumnDefinition Width="20"></ColumnDefinition>-->
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Title}"></TextBlock>
<TextBox Text="{Binding Uw}"></TextBox>
<!-- <TextBox Text="{Binding Partner}"></TextBox>-->
</Grid>
</DataTemplate></ListBox.ItemTemplate>
</ListBox>
then in my code behind I have :
public DefaultSettings()
{
InitializeComponent();
List<EurItem> items = new List<EurItem>
{
new EurItem() { Title = "Couple", Uw = 190m, Partner = 170m },
new EurItem() { Title = "Family", Uw = 180m, Partner = 160m }
};
lbEurInsuredType.ItemsSource = items;
}
What happens is that If I Only have the TextBlock in the xaml, then the title shows in the listbox, as soon as I start to introduce other members, then it displays the last item that has been bound and looses all the others.
This is unnecessary because you are already directly setting it in your code behind.
ItemsSource="{Binding}"
Also, you are not setting any Grid.Column definitions on your succeeding elements. So they are overlapping each other.
You might want something like this
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="30"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Title}"></TextBlock>
<TextBox Text="{Binding Uw}" Grid.Column="1"></TextBox>
<TextBox Text="{Binding Partner}" Grid.Column="2"></TextBox>
</Grid>
You're placing several controls in a Grid with several columns. By default, each item you place inside a Grid is shown in the first row and first column.
Since you're not telling the controls otherwise, all your controls are being added to the first row and column, overlapping each other... So only the last control is shown.
You need to use Grid.Column to specify which column should each control be placed in.
<ListBox Name="lbEurInsuredType" HorizontalContentAlignment="Stretch" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="30"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Title}"></TextBlock>
<TextBox Text="{Binding Uw}" Grid.Column="1"></TextBox>
<TextBox Text="{Binding Partner}" Grid.Column="2"></TextBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

How to copy a selected text block to another hub page in Windows phone app

I am using list view to display a list of items in a group. Here is how my list view looks like:
<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemListView"
AutomationProperties.Name="Items In Group"
TabIndex="1"
Grid.Row="1"
ItemsSource="{Binding Items}"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
SelectionMode="None"
IsSwipeEnabled="false"
Margin="19,0,0,0">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Margin="0,-9.5,0,0" Width="79" Height="79">
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}" VerticalAlignment="Top"/>
</Border>
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="14.5,0,0,0">
<TextBlock Text="{Binding Title}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Text="{Binding Description}" Style="{ThemeResource ListViewItemContentTextBlockStyle}" Foreground="{ThemeResource PhoneMidBrush}" TextWrapping="WrapWholeWords"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I would like to add a logic that when a text block is selected, it should copy the entire text block to another hub page (favorite) and create a reference back to the source text block. Whenever the user clicks any text block, it should be copied to the existing list of favorite blocks on Favorite hub page. Also, the user should be able to select the block on the favorite and remove it from the favorite list.
Currently, my "ItemView_ItemClick event looks like below which get the Id of the selecte item in the list, but I don't know how to proceed to implement above logic.
private void ItemView_ItemClick(object sender, ItemClickEventArgs e)
{
var itemId = ((SampleDataItem)e.ClickedItem).UniqueId;
if (!Frame.Navigate(typeof(ItemPage), itemId))
{
var resourceLoader = ResourceLoader.GetForCurrentView("Resources");
throw new Exception(resourceLoader.GetString("NavigationFailedException`enter code here`Message"));
}
You can use IsolatedStorageSettings for local storage.

Programmatically create listbox with datatemplate and binding data

I'm working on Windows store app. Is there any way to programmatically create a listbox with datatemplate and then to bind data to datatemplate items?
I have created this listbox but now I need to create the same listbox programmatically because I need to create listboxes dynamically(count of listboxes is dynamic),
The second problem: I need to bind text to listbox datatemplate items. Does someone know something to recommend to me?
XAML:
<ListBox x:Name="lbTransitNow" ItemsSource="{Binding MyDataBusStationsCurrent}" SelectionChanged="LbTransitNow_OnSelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate >
<StackPanel>
<Grid x:Name="gridTodayBtn">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tbTransitStart" Grid.Column="0" Text="{Binding Lines_departure_date}" />
<TextBlock x:Name="tbTransitEnd" Grid.Column="1" Text="{Binding Lines_arrival_date}" />
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code:
foreach (var routs in cpStationsrs.RoutesList)
{
foreach (var lines in routs.LinesList)
{
foreach (var stops in lines.StopsList)
{
_myDataBusStationsChoosen.Add(new BindingData
{
Lines_stops_nameSub = stops.Name,
Lines_stops_timeSub = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, stops.Time.Hour, stops.Time.Minute, 0).ToString("dd.MM.yyyy -- HH:mm"),
Lines_nameSub = lines.Name,
...
});
}
}
}
OnPropertyChanged("MyDataBusStationsChoosen");
As far as I know, there is no way to create a DataTemplate programmatically in WinRT. However, if I understand your question correctly, you can reuse the same template for all listboxes... So you could just declare the template in the resources and reference it in each ListBox.
<Page.Resources>
<DataTemplate x:Key="myItemTemplate">
<StackPanel>
<Grid x:Name="gridTodayBtn">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="tbTransitStart" Grid.Column="0" Text="{Binding Lines_departure_date}" />
<TextBlock x:Name="tbTransitEnd" Grid.Column="1" Text="{Binding Lines_arrival_date}" />
</Grid>
</StackPanel>
</DataTemplate>
</Page.Resources>
Then, in code:
var listBox = new ListBox { ItemTemplate = (DataTemplate)Resources["myItemTemplate"] }

How to Add dynamic control instead of static control?

I have a collection with fields cityname, statename and countryname and I bind that collection to my wpf form. I want to display the cityname in a Textbox, the statename in a combobox and the countryname in a combobox. All the textboxes and comboboxes should come dynamically. How can I do this job?
Any one suggest me how to design this form dynamically in wpf using MVVM I am trying to do this code but not get result properly. Either I get everything as textbox or combobox, but what i need is textbox and combobox as specified.
<Border Margin="3.5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="125" />
<ColumnDefinition Width="*" MinWidth="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock x:Name="tbFieldTag" Cursor="Hand" VerticalAlignment="Center" HorizontalAlignment="Stretch" TextWrapping="Wrap" Margin="10,0,0,0" Text="{Binding Path=CardField.FieldTag}" />
<TextBox Margin="10,0,0,0" x:Name="txtFieldData" Grid.Column="1" MaxLength="{Binding Path=CardField.MaximumLength}" Text="{Binding Path=CardField.FieldData, Mode=TwoWay}" />
<!--<ComboBox Margin="10,0,0,0" x:Name="comboFieldData" Grid.Column="1" Text="{Binding Path=CardField.FieldTag}"/>-->
</Grid>
</Border>
The key to your problem are DataTemplates. These allow you to bind your view to a collection of custom objects.
You should have a ViewModel that is exposing an ObservableCollection<TLocation> where TLocation is a class that is exposing public properties Cityname, Statename and Countryname.
In your View you need to show a ContentControl, say a ListBox, having it's ItemSource property bound to the ObservableCollection.
Then you set the DataTemplate for the Listbox to something like:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Path=CityName}" />
<ComboBox Text="{Binding Path=StateName}" />
<ComboBox Text="{Binding Path=CountryName}" />
</StackPanel>
</DataTemplate>
Another approach is to use a DataGrid. See this article

Categories