Skip to content

Instantly share code, notes, and snippets.

@mecab
Created June 21, 2012 17:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mecab/2967152 to your computer and use it in GitHub Desktop.
Save mecab/2967152 to your computer and use it in GitHub Desktop.
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="App1.SearchResultsPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
IsTabStop="false"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:common="using:App1.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:ExtensionType="Search">
<Page.Resources>
<CollectionViewSource x:Name="resultsViewSource" Source="{Binding Results}"/>
<CollectionViewSource x:Name="filtersViewSource" Source="{Binding Filters}"/>
<common:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<!-- TODO: キー AppName が App.xaml で宣言されている場合は、この行を削除します -->
<x:String x:Key="AppName">マイ アプリケーション</x:String>
</Page.Resources>
<!--
このグリッドは 2 つの行を定義するページのルート パネルとして機能します:
* 行 0 には [戻る] ボタンおよびページ タイトルが含まれます
* 行 1 には残りのページ レイアウトが含まれます
-->
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- [戻る] ボタン、ページ タイトル、およびサブタイトル-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Grid.Column="0" Click="GoBack" Style="{StaticResource BackButtonStyle}" IsEnabled="{Binding Frame.CanGoBack, ElementName=pageRoot}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="{StaticResource AppName}" Style="{StaticResource PageHeaderTextStyle}" />
<TextBlock x:Name="resultText" Grid.Column="2" Text="Results for&#x00a0;" Style="{StaticResource PageSubheaderTextStyle}"/>
<TextBlock x:Name="queryText" Grid.Column="3" Text="{Binding QueryText}" Style="{StaticResource PageSubheaderTextStyle}"/>
</Grid>
<Grid x:Name="resultsPanel" Grid.Row="1">
<!--
ほとんどのビューステート内のページ本体は、アイテム コントロールを使用して、検索結果の水平スクロール グリッドの上に、
フィルター処理用の複数のオプション ボタンを作成します
-->
<Grid x:Name="typicalPanel">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ItemsControl
x:Name="filtersItemsControl"
ItemsSource="{Binding Source={StaticResource filtersViewSource}}"
Visibility="{Binding ShowFilters, Converter={StaticResource BooleanToVisibilityConverter}}"
Margin="120,-3,120,30">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding Description}"
GroupName="Filters"
IsChecked="{Binding Active, Mode=TwoWay}"
Checked="Filter_Checked"
Style="{StaticResource TextRadioButtonStyle}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<GridView
x:Name="resultsGridView"
AutomationProperties.AutomationId="ResultsGridView"
AutomationProperties.Name="Search Results"
TabIndex="1"
Grid.Row="1"
Margin="0,2,0,0"
Padding="110,0,110,46"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding Source={StaticResource resultsViewSource}}"
ItemTemplate="{StaticResource StandardSmallIcon300x70ItemTemplate}"
ItemClick="resultsGridView_ItemClick_1">
<GridView.ItemContainerStyle>
<Style TargetType="Control">
<Setter Property="Height" Value="70"/>
<Setter Property="Margin" Value="0,0,38,8"/>
</Style>
</GridView.ItemContainerStyle>
</GridView>
</Grid>
<!--
The body of the page when snapped uses a combo box to select a filter above a
vertical scrolling list of search results
-->
<Grid x:Name="snappedPanel" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ComboBox
ItemsSource="{Binding Source={StaticResource filtersViewSource}}"
Visibility="{Binding ShowFilters, Converter={StaticResource BooleanToVisibilityConverter}}"
Margin="20,0,20,20"
SelectionChanged="Filter_SelectionChanged"
HorizontalAlignment="Left"/>
<ListView
x:Name="resultsListView"
AutomationProperties.AutomationId="ResultsListView"
AutomationProperties.Name="Search Results"
TabIndex="1"
Grid.Row="1"
Margin="16,0,0,0"
Padding="0,0,0,60"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding Source={StaticResource resultsViewSource}}"
ItemTemplate="{StaticResource StandardSmallIcon70ItemTemplate}">
<ListView.ItemContainerStyle>
<Style TargetType="Control">
<Setter Property="Height" Value="70"/>
<Setter Property="Margin" Value="0,0,18,8"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Grid>
<TextBlock
x:Name="noResultsTextBlock"
Grid.Row="1"
Margin="120,50,0,0"
Visibility="Collapsed"
Style="{StaticResource SubheaderTextStyle}"
Text="No results match your search." />
<VisualStateManager.VisualStateGroups>
<!--表示状態には、アプリケーションのビューステートが反映されます -->
<VisualStateGroup x:Name="ApplicationViewStates">
<VisualState x:Name="FullScreenLandscape"/>
<VisualState x:Name="Filled"/>
<!-- ページ全体では、縦方向に対して、より狭い 100 ピクセルの余白の規則を優先します -->
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PortraitBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filtersItemsControl" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="100,-3,90,30"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="resultsGridView" Storyboard.TargetProperty="Padding">
<DiscreteObjectKeyFrame KeyTime="0" Value="96,0,86,56"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="noResultsTextBlock" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="100,50,0,0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<!--
スナップの場合、[戻る] ボタンとタイトルはスタイルが異なり、次のような大幅な変更が加えられます:
* クエリ テキストはページ ヘッダーになります
* フィルター選択と検索結果に異なる表現が使用されます
-->
<VisualState x:Name="Snapped">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="backButton" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedBackButtonStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="queryText" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource SnappedPageHeaderTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="pageTitle" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="resultText" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="typicalPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="snappedPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="noResultsTextBlock" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="20,0,0,0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="noResultsTextBlock" Storyboard.TargetProperty="Style">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource BaselineTextStyle}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name = "ResultStates">
<VisualState x:Name="ResultsFound" />
<!-- When there are no results, the results panel is replaced with an informational TextBlock -->
<VisualState x:Name="NoResultsFound">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="resultsPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="noResultsTextBlock" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</common:LayoutAwarePage>
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// 検索コントラクトのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234240 を参照してください
namespace App1
{
/// <summary>
/// このページには、グローバル検索がこのアプリケーションに指定されている場合に、検索結果が表示されます。
/// </summary>
public sealed partial class SearchResultsPage : App1.Common.LayoutAwarePage
{
//private UIElement _previousContent;
//private ApplicationExecutionState _previousExecutionState;
public SearchResultsPage()
{
this.InitializeComponent();
}
/// <summary>
/// Determines how best to support navigation back to the previous application state.
/// </summary>
public static void Activate(String queryText, ApplicationExecutionState previousExecutionState)
{
var previousContent = Window.Current.Content;
var frame = previousContent as Frame;
if (frame != null)
{
// If the app is already running and uses top-level frame navigation we can just
// navigate to the search results
frame.Navigate(typeof(SearchResultsPage), queryText);
}
else
{
// Otherwise bypass navigation and provide the tools needed to emulate the back stack
//SearchResultsPage1 page = new SearchResultsPage1();
//page._previousContent = previousContent;
//page._previousExecutionState = previousExecutionState;
//page.LoadState(queryText, null);
//Window.Current.Content = page;
var _rootFrame = new Frame();
_rootFrame.Navigate(typeof(SearchResultsPage), queryText);
Window.Current.Content = _rootFrame;
}
// Either way, active the window
Window.Current.Activate();
}
/// <summary>
/// Populates the page with content passed during navigation. Any saved state is also
/// provided when recreating a page from a prior session.
/// </summary>
/// <param name="navigationParameter">The parameter value passed to
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
/// </param>
/// <param name="pageState">A dictionary of state preserved by this page during an earlier
/// session. This will be null the first time a page is visited.</param>
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
var queryText = navigationParameter as String;
// TODO: Application-specific searching logic. The search process is responsible for
// 結果カテゴリのリストを作成する必要があります。
//
// filterList.Add(new Filter("<フィルター名>", <結果数>));
//
// アクティブな状態で開始するには、3 番目の引数として true を渡すフィルターが最初
// のフィルター (通常は "All") のみであることが必要です。アクティブ フィルターの
// 結果は以下の Filter_SelectionChanged で提供されます。
var filterList = new List<Filter>();
filterList.Add(new Filter("All", 0, true));
// ビュー モデルを介して結果を通信します
this.DefaultViewModel["QueryText"] = '\u201c' + queryText + '\u201d';
// this.DefaultViewModel["CanGoBack"] = this._previousContent != null;
this.DefaultViewModel["Filters"] = filterList;
this.DefaultViewModel["ShowFilters"] = filterList.Count > 1;
}
/// <summary>
/// [前へ] がクリックされたときに呼び出されます。
/// </summary>
/// <param name="sender">[戻る] ボタンを表す Button インスタンス。</param>
/// <param name="e">ボタンがどのようにクリックされたかを説明するイベント データ。</param>
protected override void GoBack(object sender, RoutedEventArgs e)
{
// 検索結果が要求されたときよりも前の状態にアプリケーションを戻します
if (this.Frame != null && this.Frame.CanGoBack)
{
this.Frame.GoBack();
}
// else if (this._previousContent != null)
// {
// Window.Current.Content = this._previousContent;
// }
else
{
// TODO: invoke the app's normal launch behavior, using this._previousExecutionState
// as appropriate. Exact details can vary from app to app, which is why an
// implementation isn't included in the Search Contract template. Typically
// this method and OnLaunched in App.xaml.cs can call a common method.
}
}
/// <summary>
/// スナップ ビューステートの ComboBox を使用してフィルターが選択されたときに呼び出されます。
/// </summary>
/// <param name="sender">ComboBox インスタンス。</param>
/// <param name="e">選択されたフィルターがどのように変更されたかを説明するイベント データ。</param>
void Filter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// 選択されたフィルターを確認します
var selectedFilter = e.AddedItems.FirstOrDefault() as Filter;
if (selectedFilter != null)
{
// 対応する Filter オブジェクト内に結果をミラー化し、
// いない場合に RadioButton 表現を使用して変更を反映できるようにします
selectedFilter.Active = true;
// TODO: this.DefaultViewModel["Results"] をバインド可能な Image、Title、および Subtitle の
// to a collection of items with bindable Image, Title, Subtitle, and Description properties
// Ensure results are found
object results;
ICollection resultsCollection;
if (this.DefaultViewModel.TryGetValue("Results", out results) &&
(resultsCollection = results as ICollection) != null &&
resultsCollection.Count != 0)
{
VisualStateManager.GoToState(this, "ResultsFound", true);
return;
}
}
// Display informational text when there are no search results.
VisualStateManager.GoToState(this, "NoResultsFound", true);
}
/// <summary>
/// スナップ化されていない場合に RadioButton を使用してフィルターが選択されたときに呼び出されます。
/// </summary>
/// <param name="sender">選択された RadioButton インスタンス。</param>
/// <param name="e">RadioButton がどのように選択されたかを説明するイベント データ。</param>
void Filter_Checked(object sender, RoutedEventArgs e)
{
// 対応する ComboBox で使用される CollectionViewSource に変更をミラー化して
// スナップ化されたときに変更が反映されるようにします
if (filtersViewSource.View != null)
{
var filter = (sender as FrameworkElement).DataContext;
filtersViewSource.View.MoveCurrentTo(filter);
}
}
/// <summary>
/// 検索結果の表示に使用できるフィルターの 1 つを表すビュー モデルです。
/// </summary>
private sealed class Filter : App1.Common.BindableBase
{
private String _name;
private int _count;
private bool _active;
public Filter(String name, int count, bool active = false)
{
this.Name = name;
this.Count = count;
this.Active = active;
}
public override String ToString()
{
return Description;
}
public String Name
{
get { return _name; }
set { if (this.SetProperty(ref _name, value)) this.OnPropertyChanged("Description"); }
}
public int Count
{
get { return _count; }
set { if (this.SetProperty(ref _count, value)) this.OnPropertyChanged("Description"); }
}
public bool Active
{
get { return _active; }
set { this.SetProperty(ref _active, value); }
}
public String Description
{
get { return String.Format("{0} ({1})", _name, _count); }
}
}
private void resultsGridView_ItemClick_1(object sender, ItemClickEventArgs e)
{
this.Frame.Navigate(typeof(ItemDetailPage), (e.ClickedItem as Data.SampleDataItem).UniqueId);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment