windows-phone-7 – 全景wp7 mvvm中的静态和动态全景项目
这是我的情况.
ViewModelA { ObservableCollection<Items> ItemsA ObservableCollection<ViewModelB> ViewModelBs } 使用设置为ViewModel A的datacontext查看A. 我想在运行时使用commond数据模板(列表框,文本块等)将其他全景项添加到全景控件中.每个全景项将在运行时绑定到ViewModelBs集合中的每个ViewModelB. 我并不反对为此做一些代码隐藏的东西,因为我不是一个严格的mvvm纯粹主义者. 这是一些我试过工作失败的代码片段.希望它提供一些想法.. <phone:PhoneApplicationPage.Resources> <Style x:Key="PanoramaItemStyle" TargetType="ContentControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ContentControl"> <Grid x:Name="ContentGrid"> <controls:PanoramaItem x:Name="ItemLocationPanoramaItem" Header="{Binding TagName}"> <StackPanel > <ListBox x:Name="ItemLocatorsList" ItemsSource="{Binding ItemLocators}" Height="496" SelectedItem="{Binding SelectedItemLocation,Mode=TwoWay}" > <Custom:Interaction.Triggers> <Custom:EventTrigger EventName="SelectionChanged"> <GalaSoft_MvvmLight_Command:EventToCommand x:Name="SelectionChangedEvent" Command="{Binding RelativeSource={RelativeSource TemplatedParent},Path=DataContext.GoToEditItemLocatorCommand}" PassEventArgsToCommand="True"/> </Custom:EventTrigger> </Custom:Interaction.Triggers> <ListBox.ItemsPanel> <ItemsPanelTemplate > <StackPanel Orientation="Vertical" ScrollViewer.VerticalScrollBarVisibility="Auto" /> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <StackPanel Orientation="Horizontal" Margin="0,17"> <StackPanel Width="311"> <TextBlock Text="{Binding Path=Item.Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextLargeStyle}"/> <TextBlock Text="{Binding Path=Location.Description}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/> </StackPanel> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </controls:PanoramaItem> <ContentPresenter/> </Grid> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="Foreground" Value="White"/> </Style> </phone:PhoneApplicationPage.Resources> 代码隐藏: public LocationGroups() { InitializeComponent(); LocationGroupsPanaroma.DefaultItem = LocationGroupsPanaroma.Items[0]; viewModel = this.DataContext as LocationGroupsViewModel; CreateDynamicPanaromaItems(); } private void CreateDynamicPanaromaItems() { foreach (Model.LocationGroup group in viewModel.LocationGroups) { if (group.TotalItems > 0) { PanoramaItem pi = new PanoramaItem(); pi.Header = group.Name; pi.Orientation = System.Windows.Controls.Orientation.Horizontal; ItemLocationListViewModel itemLocationViewModel = viewModel[group.LocationGroupId]; pi.DataContext = itemLocationViewModel; pi.Style = Resources["PanoramaItemStyle"] as Style; LocationGroupsPanaroma.Items.Add(pi); } } } 编辑 ViewModel A有 Items collection Collection of ViewModelBs panaroma数据上下文设置为viewmodelA panaroma item - Statitically created in xaml to some Items collection in ViewModelA This pan item has a list box panaroma items --- to be bound to collection of viewmodelbs These pan items should each have a listbox which is selectable and bound to some collection in View Model B and fires commands on selection changed to viewModelB. Currently using the galasoft eventtocommand to hook the selection changed on the list box to a relay command. The problem is that this eventtommand should have the viewmodel as its data context and the not the collection (bound to the listbox) within viewmodel.
好的,终于有时间回答这个问题了.提出的解决方案不需要任何代码,仅依赖于MVVM概念和数据绑定.
概念上,Panorama控件是一个ItemPresenter(它继承自ItemsPresenter),即您可以将ItemsSource绑定到包含重复您的PanoramaItems的项目的列表. 要渲染PanoramaItem,您必须提供Panorama.HeaderTemplate和Panorama.ItemTemplate的模板.模板内的DataContext是代表PanoramaItem的ViewModel.如果此ViewModel包含项目列表,您现在可以使用它来生成您正在寻找的ListBoxes. 以下是样本…… ViewModelLocator.cs using GalaSoft.MvvmLight; namespace WP7Test.ViewModel { public class ViewModelLocator { private static MainViewModel _main; public ViewModelLocator() { if (ViewModelBase.IsInDesignModeStatic) { // Create design time services and viewmodels } else { // Create run time services and view models } _main = new MainViewModel(); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance","CA1822:MarkMembersAsStatic",Justification = "This non-static member is needed for data binding purposes.")] public MainViewModel Main { get { return _main; } } } } MainViewModel.cs public class MainViewModel : ViewModelBase { public MainViewModel() { this.Items = new ObservableCollection<ItemViewModel>(); if (IsInDesignMode) { // Code runs in Blend --> create design time data. } else { // Code runs "for real" } this.LoadData(); } #region [Items] public const string ItemsPropertyName = "Items"; private ObservableCollection<ItemViewModel> _items = default(ObservableCollection<ItemViewModel>); public ObservableCollection<ItemViewModel> Items { get { return _items; } private set { if (_items == value) { return; } var oldValue = _items; _items = value; RaisePropertyChanged(ItemsPropertyName); } } #endregion private void LoadData() { this.Items.Add(new ItemViewModel() { LineOne = "runtime one",LineTwo = "Maecenas praesent accumsan bibendum",LineThree = "Facilisi faucibus habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu" }); this.Items.Add(new ItemViewModel() { LineOne = "runtime two",LineTwo = "Dictumst eleifend facilisi faucibus",LineThree = "Suscipit torquent ultrices vehicula volutpat maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus" }); this.Items.Add(new ItemViewModel() { LineOne = "runtime three",LineTwo = "Habitant inceptos interdum lobortis",LineThree = "Habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu suscipit torquent" }); foreach (var item in Items) { for (int i = 0; i < 5; ++i) item.Items.Add(new ItemViewModel() { LineOne = "Item " + i,LineTwo = "Maecenas praesent accumsan bibendum" }); } } } ItemViewModel.cs public class ItemViewModel : ViewModelBase { public ItemViewModel() { this.Items = new ObservableCollection<ItemViewModel>(); if (IsInDesignMode) { // Code runs in Blend --> create design time data. } else { // Code runs "for real": Connect to service,etc... } } public override void Cleanup() { // Clean own resources if needed base.Cleanup(); } #region [LineOne] public const string LineOnePropertyName = "LineOne"; private string _lineOne = default(string); public string LineOne { get { return _lineOne; } set { if (_lineOne == value) { return; } var oldValue = _lineOne; _lineOne = value; RaisePropertyChanged(LineOnePropertyName); } } #endregion #region [LineTwo] public const string LineTwoPropertyName = "LineTwo"; private string _lineTwo = default(string); public string LineTwo { get { return _lineTwo; } set { if (_lineTwo == value) { return; } var oldValue = _lineTwo; _lineTwo = value; RaisePropertyChanged(LineTwoPropertyName); } } #endregion #region [LineThree] public const string LineThreePropertyName = "LineThree"; private string _lineThree = default(string); public string LineThree { get { return _lineThree; } set { if (_lineThree == value) { return; } var oldValue = _lineThree; _lineThree = value; RaisePropertyChanged(LineThreePropertyName); } } #endregion #region [Items] public const string ItemsPropertyName = "Items"; private ObservableCollection<ItemViewModel> _items = default(ObservableCollection<ItemViewModel>); public ObservableCollection<ItemViewModel> Items { get { return _items; } private set { if (_items == value) { return; } var oldValue = _items; _items = value; RaisePropertyChanged(ItemsPropertyName); } } #endregion } MainPage.xaml中 <phone:PhoneApplicationPage x:Class="WP7Test.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:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls" 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="800" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="False"> <!--LayoutRoot is the root grid where all page content is placed--> <Grid x:Name="LayoutRoot" Background="Transparent" DataContext="{Binding Main,Source={StaticResource Locator}}"> <controls:Panorama Title="my application" ItemsSource="{Binding Items}"> <controls:Panorama.Background> <ImageBrush ImageSource="PanoramaBackground.png"/> </controls:Panorama.Background> <controls:Panorama.HeaderTemplate> <DataTemplate> <TextBlock Text="{Binding LineOne}"/> </DataTemplate> </controls:Panorama.HeaderTemplate> <controls:Panorama.ItemTemplate> <DataTemplate> <StackPanel> <Border BorderThickness="0,1" BorderBrush="White"> <TextBlock Text="{Binding LineTwo}" FontSize="28" TextWrapping="Wrap"/> </Border> <Border BorderThickness="0,1" Margin="0,20" BorderBrush="White"> <TextBlock Text="{Binding LineThree}" TextWrapping="Wrap"/> </Border> <ListBox ItemsSource="{Binding Items}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding LineOne}" FontSize="24"/> <TextBlock Text="{Binding LineTwo}" FontSize="18" Margin="24,5"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </DataTemplate> </controls:Panorama.ItemTemplate> </controls:Panorama> </Grid> <!--Panorama-based applications should not show an ApplicationBar--> </phone:PhoneApplicationPage> 编辑 – 添加其他第一个面板 最后,我明白了你想要实现的目标!但是,您仍然无需执行任何代码!你只需要一个模板……对于这个Blend确实可以帮到你,因为它可以让你为一个现有的控件提取模板……好的,这里是变化. 首先,我向MainViewModel添加了一个新属性来显示一些数据: #region [MainPageProperty] public const string MainPagePropertyPropertyName = "MainPageProperty"; private string _mainPageProperty = "Facilisi faucibus habitant inceptos interdum lobortis nascetur pharetra placerat pulvinar sagittis senectus sociosqu"; public string MainPageProperty { get { return _mainPageProperty; } set { if (_mainPageProperty == value) { return; } _mainPageProperty = value; RaisePropertyChanged(MainPagePropertyPropertyName); } } #endregion 然后我使用Blend获取Panorama控件的模板并将其插入控件:Panorama元素. <controls:Panorama.Template> <ControlTemplate TargetType="controls:Panorama"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <controlsPrimitives:PanningBackgroundLayer x:Name="BackgroundLayer" HorizontalAlignment="Left" Grid.RowSpan="2"> <Border x:Name="background" Background="{TemplateBinding Background}" CacheMode="BitmapCache"/> </controlsPrimitives:PanningBackgroundLayer> <controlsPrimitives:PanningTitleLayer x:Name="TitleLayer" CacheMode="BitmapCache" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" FontSize="187" FontFamily="{StaticResource PhoneFontFamilyLight}" HorizontalAlignment="Left" Margin="10,-76,9" Grid.Row="0"/> <controlsPrimitives:PanningLayer x:Name="ItemsLayer" HorizontalAlignment="Left" Grid.Row="1"> <StackPanel Orientation="Horizontal"> <controls:PanoramaItem Header="Main panel" Width="432"> <TextBlock Text="{Binding ElementName=LayoutRoot,Path=DataContext.MainPageProperty}" TextWrapping="Wrap"/> </controls:PanoramaItem> <ItemsPresenter x:Name="items"/> </StackPanel> </controlsPrimitives:PanningLayer> </Grid> </ControlTemplate> </controls:Panorama.Template> 这里有两个技巧,首先我插入一个StacPanel,允许在controlPrimitives下面有多个元素:PanningLayer,名称为ItemsPanel.在这个StackPanel中,我移动了ItemsPresenter并添加了另一个PanoramaItem.但有一件重要的事情是设置PanoramaItem的Width属性,否则面板将扩展到所需的房间. 另一个技巧是,为了访问DataContext,我必须在Binding中使用ElementName. 希望这能展示MVVM和模板的力量! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 添加HTTPS端点后,我收到此警告:在证书存储中找不到“Micro
- .net – DateTime.Parse在XP vs Windows 7/8上有所不同
- Windows TCP套接字recv延迟
- windows – 将特定列从一个文本文件复制到另一个文本文件
- windows-server-2003 – 为什么Server 2003没有系统还原?
- Windows10:Opencv4.0+Opencv4.0.1_contrib编译
- windows-server-2003 – 在Windows 2003服务器上执行远程命
- 如何在Cygwin Windows中的HTTPS URL上运行wget时修复证书错
- 使用typescript重新定义window.console
- Windows – 禁用Office和删除权限的共享网络驱动器导致无法
- 为什么我在Get-Module的结果中没有列出Microsoft
- 如果我不知道它的类型,如何从远程计算机获取注册
- Windows – 命令提示符下的基本文本编辑器?
- 在Windows对话框中处理WM_ERASEBKGND时如何避免闪
- 无法在Windows上安装python lxml(和libxml2)
- HTTPERR日志关闭方法
- windows – 如何在git bash中设置正确的本地时区
- windows-xp – Windows XP上的_InterlockedCompa
- windows-phone-8 – WP8实时图块中的计数是否有最
- windows-store-apps – 应用程序通过WACK但未通过