I think the question says it all: I want to build an Windows 8 Store app but how can I build an UI like this:
I think left is a normal ListView. The important thing is that I want an own AppBar for each ListViewEntry. And how can I load different pages (with different AppBars) in the right content area?
You can put a ContentControl in the main panel and another one in the AppBar, then bind their Content properties to the SelectedItem property of the ListBox on the left and use ContentTemplateSelector to display the right UI for the selected page.
*EDIT - Sample
XAML
<Page
x:Class="App17.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App17"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<local:PropertyPageTemplateSelector
x:Key="PropertyPageTemplateSelector"/>
</Page.Resources>
<Grid
Background="LemonChiffon">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition
Width="2*" />
</Grid.ColumnDefinitions>
<ListBox
x:Name="listBox"
DisplayMemberPath="Label"/>
<ContentControl
Grid.Column="1"
Content="{Binding SelectedItem, ElementName=listBox}"
ContentTemplateSelector="{StaticResource PropertyPageTemplateSelector}">
<ContentControl.Resources>
<DataTemplate
x:Key="Options">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="Aquamarine" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="Preferences">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="Khaki" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="Properties">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="LawnGreen" />
</StackPanel>
</DataTemplate>
<DataTemplate
x:Key="Settings">
<StackPanel>
<TextBlock
Text="{Binding Label}"
FontSize="32"
Foreground="SlateGray" />
<Rectangle
Width="400"
Height="400"
Fill="Violet" />
</StackPanel>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</Grid>
</Page>
C#
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace App17
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
listBox.ItemsSource =
new List<PropertyPageViewModel>(
new PropertyPageViewModel[]
{
new OptionsPropertyPageViewModel(),
new PreferencesPropertyPageViewModel(),
new PropertiesPropertyPageViewModel(),
new SettingsPropertyPageViewModel(),
});
}
}
public abstract class PropertyPageViewModel
{
public abstract string Label { get; }
}
public class OptionsPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Options"; } }
}
public class PreferencesPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Preferences"; } }
}
public class PropertiesPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Properties"; } }
}
public class SettingsPropertyPageViewModel : PropertyPageViewModel
{
public override string Label { get { return "Settings"; } }
}
public class PropertyPageTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item == null) return base.SelectTemplateCore(item, container);
var contentControl = (ContentControl)container;
var viewModel = (PropertyPageViewModel)item;
var templateKey = viewModel.Label;
return (DataTemplate)contentControl.Resources[templateKey];
}
}
}
Related
How can i deserialize this jsonx variable and put it on a longlistselector on windows phone?
Currently i can only echo one string with messagebox. i need key-value sets on a longlistselector.
edit: this is my answer http://pastebin.com/CcADHaab
here is my code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using PhoneApp5.Resources;
using Newtonsoft.Json;
namespace PhoneApp5
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
string json = #"{
'Email': 'james#example.com',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z'
}";
string jsonx = #"{
'Table1': [
{
'id': 0,
'item': 'item 0'
},
{
'id': 1,
'item': 'item 1'
}
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
// Console.WriteLine(account.Email);
// james#example.com
MessageBox.Show(account.Email);
list.ItemsSource = new BookList();
}
}
public class BookList : List<Account>
{
public BookList()
{
}
}
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
// public IList<string> Roles { get; set; }
}
///////////////////////////
}
and my XAML
<phone:PhoneApplicationPage
x:Class="PhoneApp5.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector Name="list">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding id}" />
<TextBlock Text=" ( " />
<TextBlock Text="{Binding item}" FontStyle="Italic" />
<TextBlock Text=" )" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
You need a class to represent your json:
public class MyClass
{
public string Id { get; set; }
public string Item { get; set; }
}
Set a ObservableCollection property in your Form:
public ObservableCollection<MyClass> MyClassCollection { get; set; }
and then set the MyClassCollection property to your Deserialized json
MyClassCollection = JsonConvert.DeserializeObject<ObservableCollection<MyClass>>(e.Result);
That way you're binding your class list to the LongListSelector Control in your XAML:
<phone:LongListSelector Name="list" ItemsSource="{Binding MyClassCollection}">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding id}" />
<TextBlock Text=" ( " />
<TextBlock Text="{Binding item}" FontStyle="Italic" />
<TextBlock Text=" )" />
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
That should work.
I am using MVVM Light, Autofac for windows phone 7 and Autofac locator.
With autofac
http://www.nuget.org/packages/Autofac.Wp7
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
using MvvmLight1.Model;
using Autofac;
namespace MvvmLight1.ViewModel
{
public class ViewModelLocator
{
static ViewModelLocator()
{
var builder = new ContainerBuilder();
builder.RegisterType<MainViewModel>();
var container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
}
}
using Microsoft.Phone.Controls;
namespace MvvmLight1
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
var main = this.DataContext as MainPage; // will be null
}
}
}
<phone:PhoneApplicationPage x:Class="MvvmLight1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait"
Orientation="Portrait"
d:DesignWidth="480"
d:DesignHeight="768"
shell:SystemTray.IsVisible="True"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<!--LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot"
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel"
Grid.Row="0"
Margin="24,24,0,12">
<TextBlock x:Name="ApplicationTitle"
Text="{Binding ApplicationTitle}"
Style="{StaticResource PhoneTextNormalStyle}" />
<TextBlock x:Name="PageTitle"
Text="{Binding PageName}"
Margin="-3,-8,0,0"
Style="{StaticResource PhoneTextTitle1Style}" />
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentGrid"
Grid.Row="1">
<TextBlock Text="{Binding WelcomeTitle}"
Style="{StaticResource PhoneTextNormalStyle}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="40"
TextWrapping="Wrap"
TextAlignment="Center" />
</Grid>
</Grid>
</phone:PhoneApplicationPage>
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Autofac;
using Microsoft.Practices.ServiceLocation;
namespace MvvmLight1
{
public sealed class AutofacServiceLocator : ServiceLocatorImplBase
{
readonly IComponentContext _container;
public AutofacServiceLocator(IComponentContext container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
protected override object DoGetInstance(Type serviceType, string key)
{
return key != null ? _container.ResolveNamed(key, serviceType) : _container.Resolve(serviceType);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
var enumerableType = typeof(IEnumerable<>).MakeGenericType(serviceType);
object instance = _container.Resolve(enumerableType);
return ((IEnumerable)instance).Cast<object>();
}
}
}
using GalaSoft.MvvmLight;
using MvvmLight1.Model;
namespace MvvmLight1.ViewModel
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
}
}
}
now the viewModel in my constructor of MainPage.cs will always be null.
When I just used SimpleIoc it was filled with the Main Object.
I am developing a WP7 app that contains a LongListSelector. Within the ItemTemplate there is a ListPicker. I select a value from the ListPicker for the first item in the LongListSelector, then select a value from the ListPicker for the 2nd item. If I then scroll down the page and back to the top again, the value I selected in the ListPicker for the 1st item will be reset (SelectedIndex=0).
I have put code in the Link and Unlink events of the LongListSelector to write to the output window and I have found that when the 1st item unlinks (due to scrolling down the page), the ListPicker value is what I selected but as soon as the link event fires (due to scrolling back up the page) for the 1st item the value is reset.
Im using ObserableCollection and implement the INPC interface for my objects and the ViewModel updates when the ListPicker selection is changed.
How can I ensure that the value in the ListPickers are retaining during scrolling of the LongListSelector?
MainPage.xaml
<phone:PhoneApplicationPage
x:Class="LongListSelector.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="5000"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit">
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Name="occurrenceItemTemplate">
<Grid>
<StackPanel Orientation="Vertical" Margin="5,0,0,0" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Name="tbkEventDateTime" Grid.Row="0" Grid.Column="0"
Text="{Binding ItemNumber}"
Style="{StaticResource PhoneTextSmallStyle}" />
<!--<TextBox Name="txtEventDateTime" Grid.Row="1" Grid.Column="0"
Text="{Binding Result}" />-->
<toolkit:ListPicker Name="lpkResult" Margin="12,0,12,12"
Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding TestItemResultList, Mode=OneTime}"
SelectedIndex="{Binding Result, Mode=TwoWay}"
CacheMode="BitmapCache">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" />
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
</Grid>
</StackPanel>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" VerticalAlignment="Stretch">
<toolkit:LongListSelector x:Name="lstOutstandingOccurrences"
Margin="0,12,0,0" Padding="0,0,0,24"
ItemTemplate="{StaticResource occurrenceItemTemplate}"
ItemsSource="{Binding TestItemCollection, Mode=TwoWay}"
IsFlatList="True" ShowListHeader="False" >
</toolkit:LongListSelector>
</Grid>
</Grid>
MainPage.xaml.cs
public partial class MainPage : PhoneApplicationPage
{
private TestItemViewModel _vm;
public TestItemViewModel ViewModel
{
get
{
if (_vm == null)
_vm = new TestItemViewModel();
return _vm;
}
private set
{
_vm = value;
}
}
// Constructor
public MainPage()
{
InitializeComponent();
this.lstOutstandingOccurrences.Link += new EventHandler<LinkUnlinkEventArgs>(lstOutstandingOccurrences_Link);
this.lstOutstandingOccurrences.Unlink += new EventHandler<LinkUnlinkEventArgs>(lstOutstandingOccurrences_Unlink);
this.DataContext = this.ViewModel;
}
void lstOutstandingOccurrences_Link(object sender, LinkUnlinkEventArgs e)
{
var item = e.ContentPresenter.Content as TestItem;
Debug.WriteLine("Link event for ItemNumber {0} = {1}", item.ItemNumber, item.Result);
}
void lstOutstandingOccurrences_Unlink(object sender, LinkUnlinkEventArgs e)
{
var item = e.ContentPresenter.Content as TestItem;
Debug.WriteLine("Unlink event for ItemNumber {0} = {1}", item.ItemNumber, item.Result);
}
}
TestItemViewModel.cs
public class TestItemViewModel : BaseINPC
{
public ObservableCollection<TestItem> TestItemCollection
{
get;
private set;
}
// Constructor
public TestItemViewModel()
{
this.TestItemCollection = new ObservableCollection<TestItem>();
CreateTestData(20);
}
public void CreateTestData(int totalItems)
{
//create test data for long list selector.
for (int i = 1; i <= totalItems; i++)
{
this.TestItemCollection.Add(new TestItem(i, 0));
}
}
}
Models
public class ListHelperListItem
{
public int Value { get; set; }
public string Text { get; set; }
}
public class TestItem : BaseINPC
{
public TestItem(int ItemNumber, int Result)
{
this.ItemNumber = ItemNumber;
this.Result = Result;
}
public int ItemNumber { get; set; }
private int _Result;
public int Result
{
get
{
return _Result;
}
set
{
//if statement is for debugging purposes only.
if (this.ItemNumber == 1)
{
_Result = value;
}
_Result = value;
RaisePropertyChanged("Result");
}
}
private List<ListHelperListItem> _TestItemResultList;
public List<ListHelperListItem> TestItemResultList
{
get
{
_TestItemResultList = new List<ListHelperListItem>();
_TestItemResultList.Add(new ListHelperListItem { Value = 0, Text = " " });
_TestItemResultList.Add(new ListHelperListItem { Value = 1, Text = "Yes" });
_TestItemResultList.Add(new ListHelperListItem { Value = 2, Text = "No" });
_TestItemResultList.Add(new ListHelperListItem { Value = 3, Text = "Ignore" });
return _TestItemResultList;
}
}
}
Thanks for your help!
So, I have a code:
<tool:LongListSelector x:Name="citiesListGropus" Background="Transparent"
ItemTemplate="{StaticResource citiesItemTemplate}"
GroupHeaderTemplate="{StaticResource groupHeaderTemplate}"
GroupItemTemplate="{StaticResource groupItemTemplate}" Height="468" Margin="0,68,0,0">
<tool:LongListSelector.GroupItemsPanel>
<ItemsPanelTemplate>
<tool:WrapPanel/>
</ItemsPanelTemplate>
</tool:LongListSelector.GroupItemsPanel>
</tool:LongListSelector>
And have a DataTemplate:
<DataTemplate x:Key="groupHeaderTemplate" x:Name="groupHeaderTemplateName">
<Border Background="{StaticResource PhoneAccentBrush}" Width="75" Height="75" Margin="-333, 15, 0, 15" x:Name="groupHeaderName">
<TextBlock Text="{Binding Title}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
How can I change a property Visibility of Border in DataTemplate ? I want to hide DataTemplate. But I can't bind my data to a property such as TextBlock Text="{Binding Title}", because I make binding data once, then I need to change some properties after data binding.
Any Ideas?
UPDATE 1
So, my main goal is filter the list of cities. I want to filter them by name.
My algorithm:
1) I get data from WebService.
2) Load my ViewModel
if (!App.CitiesViewModel.IsDataLoaded)
{
App.CitiesViewModel.LoadData(serviceResponse.Result);
}
3) Group the cities by name. My code like this code.
This is important, especially for LongListSeletstor I have to use templates.
Ok, my data ready. Now I do not need a web service.
<!-- The template for city items -->
<DataTemplate x:Key="citiesItemTemplate">
<StackPanel Name="PlacePanel"
Orientation="Horizontal" Margin="0,0,0,17"
Tag="{Binding Id}" Visibility="{Binding IsVisibility}">
<Image Height="75" Width="75" HorizontalAlignment="Left" Margin="12,0,9,0" Name="Image" Stretch="Fill" VerticalAlignment="Top" Source="{Binding Image}"/>
<StackPanel Width="311">
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
I have TextBox, when I type name of a city - unnecessary cities hide. I can use data binding and INotifyPropertyChanged, so I can hide cities.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox name = (TextBox)sender;
foreach(var place in App.CitiesViewModel.Items
.Where(city => (city.Name.Contains(name.Text)) && (city.IsShow == true)))
{
city.IsVisibility = Visibility.Visible;
}
foreach (var city in App.CitiesViewModel.Items
.Where(city => !city.Name.Contains(name.Text)))
{
city.IsVisibility = Visibility.Collapsed;
}
}
But I have some problems, I can't hide this DataTemplate when I search cities:
<DataTemplate x:Key="groupHeaderTemplate" x:Name="groupHeaderTemplateName">
<Border Background="{StaticResource PhoneAccentBrush}" Width="75" Height="75" Margin="-333, 15, 0, 15" x:Name="groupHeaderName">
<TextBlock Text="{Binding Title}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
When I type name of a cities I want hide GroupHeaderTemplate. When TextBox lost focus show GroupHeaderTemplate.
I borrowed this picture here.
Update 2
My mistake was that I did not use PropertyChangedEventHandler. After adding this to GroupCity property and implementing an interface INotifyPropertyChanged I can change property Data Template after data binding.
private IList<Group<City>> citiesCollectionGroup;
var cityByName = from city in App.ViewModel.Items
group city by Convert.ToString(City.Name[0]).ToLower()
into c orderby c.Key select new
GroupCity<CitiesViewModel>(Convert.ToString(c.Key[0]).ToLower(), c);
citiesCollectionGroup = cityByName.ToList();
this.citiesListGropus.ItemsSource = citiesCollectionGroup;
public class GroupCity<T> : IEnumerable<T>, INotifyPropertyChanged
{
public GroupCity(string name, IEnumerable<T> items)
{
this.Title = name;
this.IsVisibility = Visibility.Visible;
this.Items = new List<T>(items);
}
public override bool Equals(object obj)
{
GroupCity<T> that = obj as GroupCity<T>;
return (that != null) && (this.Title.Equals(that.Title));
}
public string Title
{
get;
set;
}
private Visibility _isVisibility;
public Visibility IsVisibility
{
get
{
return _isVisibility;
}
set
{
_isVisibility = value;
NotifyPropertyChanged("IsVisibility");
}
}
public IList<T> Items
{
get;
set;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
return this.Items.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.Items.GetEnumerator();
}
#endregion
}
Xaml code:
<DataTemplate x:Key="groupHeaderTemplate" x:Name="groupHeaderTemplateName">
<Border Background="{StaticResource PhoneAccentBrush}" Width="75" Height="75" Margin="-333, 15, 0, 15" x:Name="groupHeaderName" Visibility="{Binding IsVisibility}">
<TextBlock Text="{Binding Title}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
Now we can change Visibility groupHeaderTemplate.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
foreach (GroupCity<CitiesViewModel> city in citiesCollectionGroup)
{
city.IsVisibility = Visibility.Collapsed;
}
//
}
private void SearchText_LostFocus(object sender, RoutedEventArgs e)
{
foreach (GroupCity<CitiesViewModel> city in citiesCollectionGroup)
{
city.IsVisibility = Visibility.Visible;
}
//
}
You can write your own simple DataTemplateSelector to do this. Check this out for more information.
With "How can I change a property Visibility of Border in DataTemplate ? I want to hide DataTemplate. " I understand that you want to change the visibility of an item based on a property, see example below.
(If the code below isn't quite the solution you are looking for please provide some more information about what you are trying to achieve. Re-reading your question and the comments I got on this example I doubt this is what you want to do, but I don't want to guess so I'm simply answering my interpretation of your question).
With bindings you can:
Bind the visibility property directly to a a property of type Visibility (example with listbox and Person1)
Bind the Visibility property to a boolean property, and use a converter to convert that to the Visibility type (listbox2 and Person2 + BoolToVis class).
There are more ways, but this are the two most simple to implement in my opinion.ยจ
result of code below:
View:
<phone:PhoneApplicationPage
x:Class="VisibilityWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
xmlns:VisibilityWP="clr-namespace:VisibilityWP"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.Resources>
<VisibilityWP:BoolToVis x:Key="BooleanToVisibilityConverter" />
</Grid.Resources>
<StackPanel>
<ListBox x:Name="listBox" Height="300">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Width="200" Visibility="{Binding Visibility}" Background="Blue">
<TextBlock Text="{Binding Name}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="listBox2" Height="300">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Width="200" Visibility="{Binding ShowBorder, Converter={StaticResource BooleanToVisibilityConverter}}" Background="Red">
<TextBlock Text="{Binding Name}" FontSize="40" Foreground="White" Margin="15, 15, 0, 0"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
</Grid>
Code behind:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
namespace VisibilityWP
{
public partial class MainPage
{
public MainPage()
{
InitializeComponent();
DataContext = this;
listBox.ItemsSource = new List<Person1>
{
new Person1 {Name = "Iris", Visibility = Visibility.Visible},
new Person1 {Name = "Somebody", Visibility = Visibility.Collapsed},
new Person1 {Name = "Peter", Visibility = Visibility.Visible},
};
listBox2.ItemsSource = new List<Person2>
{
new Person2 {Name = "Iris", ShowBorder = true},
new Person2 {Name = "Mia", ShowBorder = true},
new Person2 {Name = "Somebody", ShowBorder = false}
};
}
}
public class Person1
{
public string Name { get; set; }
public Visibility Visibility { get; set; }
}
public class Person2
{
public string Name { get; set; }
public bool ShowBorder { get; set; }
}
public sealed class BoolToVis : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (value is bool && (bool)value) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value is Visibility && (Visibility)value == Visibility.Visible;
}
}
}
I have a html in my property Description. When I bind this property with a textblock (ex texthide), it shows the html in textblock. But I can't bind the WebBrowser with this property. How can I bind html string to WebBrowser?
<ScrollViewer
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Margin="25, 0, 0, 0"
Grid.Row="0">
<StackPanel Orientation="Vertical">
<TextBlock
x:Name="TextHide"
Text="{Binding Path=Descrption}"
Style="{StaticResource servicesText}"
TextWrapping="Wrap" />
<phone:WebBrowser
Source="{Binding Descrption}"
x:Name="webBrowserHTML"
Foreground="Black"
Loaded="webBrowserHTML_Loaded" />
<!--<Image Source="../Images/cont_banner.png" Width="270" Grid.Row="1"/>-->
<Button Grid.Row="1">
<Button.Background>
<ImageBrush ImageSource="../Images/cont_banner.png" />
</Button.Background>
<Button.Content>
<HyperlinkButton Content="" NavigateUri="callto:3950" />
</Button.Content>
</Button>
</StackPanel>
</ScrollViewer>
Any ideas please?
Best regards
In order to be able to bind HTML directly to the WebBrowser control, you have to create an attached property:
namespace YourAppNamespace
{
public static class WebBrowserHelper
{
public static readonly DependencyProperty HtmlProperty = DependencyProperty.RegisterAttached(
"Html", typeof(string), typeof(WebBrowserHelper), new PropertyMetadata(OnHtmlChanged));
public static string GetHtml(DependencyObject dependencyObject)
{
return (string)dependencyObject.GetValue(HtmlProperty);
}
public static void SetHtml(DependencyObject dependencyObject, string value)
{
dependencyObject.SetValue(HtmlProperty, value);
}
private static void OnHtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var browser = d as WebBrowser;
if (browser == null)
return;
var html = e.NewValue.ToString();
browser.NavigateToString(html);
}
}
}
Add the required XAML Namespace declaration:
xmlns:cxi="clr-namespace:YourAppNamespace"
And use it like this:
<phone:WebBrowser cxi:WebBrowserHelper.Html="{Binding Question.Body}" />
Source