我有一個使用模板方法來設計我的用戶控件的想法。嘗試將資源模板綁定到用戶控件
這是一個自定義菜單控件。它目前作爲一個listview實現。
我想有不同風格的我的用戶控件,取決於它在我的應用程序中的使用位置。應用程序將有一個頂部菜單,右側菜單和底部菜單,至少這是現在的想法。我想爲所有菜單使用相同的用戶控件,但我也想對它們進行不同的設計,而不使用不同版本的用戶控件。
所以我的方法是在Resource/Style文件中定義不同的ControlTemplates。這些ControlTemplates用在主應用程序xaml中,並綁定在menucontainer用戶控件的SelectedTemplate依賴項屬性上。
完整的用戶控制代碼如下。這是場SelectedTemplate是準備在這裏:
<UserControl x:Class="MyApp.Views.Menu.CustomMenuContainer"
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:MyApp.Client.ViewModels"
xmlns:local="clr-namespace:MyApp.Client.Views"
xmlns:commongui="clr-namespace:MyApp.CommonGui;assembly=MyApp.CommonGui"
xmlns:menu="clr-namespace:MyApp.Client.ViewModels.Menu"
xmlns:webControls="clr-namespace:System.Web.UI.WebControls;assembly=System.Web"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="1200">
<Grid>
<ListView Background="Transparent"
BorderBrush="Black"
BorderThickness="2"
x:Name="MenuList"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Path=MenuItems}"
SelectionChanged="MenuList_OnSelectionChanged"
SelectedItem="{Binding Path=SelectedItem}"
SelectionMode="Single" >
<ListView.ItemsPanel>
<ItemsPanelTemplate x:Name="MenuPanelTemplate">
<UniformGrid IsItemsHost="True" x:Name="MenuPanel">
</UniformGrid>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.Resources>
<Style TargetType="ListViewItem" x:Name="MenuItemStyle">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="DarkSeaGreen" />
<Setter Property="Template" Value="{Binding SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
</ListView>
</Grid>
SelectedTemplate是用戶控件依賴項屬性:
public static readonly DependencyProperty SelectedTemplateProperty = DependencyProperty.Register(
"SelectedTemplate", typeof(ControlTemplate), typeof(MenuContainer), new PropertyMetadata(default(ControlTemplate)));
public ControlTemplate SelectedTemplate {
get { return (ControlTemplate)GetValue(SelectedTemplateProperty); }
set { SetValue(SelectedTemplateProperty, value); }
}
我添加了一個SelectedTemplateChanged的方法來控制時,會發生什麼模板更改:
構造函數中:
DependencyPropertyDescriptor.FromProperty(SelectedTemplateProperty, GetType()).AddValueChanged(this, SelectedTemplateChanged);
然後執行。我知道我們在模板設置在用戶控件的綁定中時輸入了這段代碼,但我無法弄清楚如何將模板應用到listview selecteditem。
private void SelectedTemplateChanged(object sender, EventArgs e)
{
//How to access and set the template of the ListView (named MenuList in the xaml) selected item from
//code behind?
//pseudocode follows:
//Find the resources of MenuList
//find trigger for isSelected
//apply the SelectedTemplate on a setter of the IsSelected trigger...
}
以下是主窗口中用戶控件的用法。
我結合從資源文件中的不同CONTROLTEMPLATES(見下文),以每個MENU1的SelectedTemplate:MenuContainer中控制
<Window x:Class="MyApp.Client.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:views="clr-namespace:MyApp.Client.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:MyApp.Client.ViewModels"
xmlns:menu1="clr-namespace:MyApp.Client.Views.Menu"
xmlns:menu="clr-namespace:MyApp.Client.ViewModels.Menu"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModels:MyAppViewModel, IsDesignTimeCreatable=True}"
Title="MainWindow" Height="800" Width="1200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding MenuViewModel.TopMenuHeigth}" MaxHeight="100" />
<RowDefinition Height="600*"/>
<RowDefinition Height="{Binding MenuViewModel.BottomMenuHeight}" MaxHeight="70"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="800*"/>
<ColumnDefinition Width="{Binding MenuViewModel.RightMenuWidth}" MaxWidth="160"/>
</Grid.ColumnDefinitions>
<Grid Name="TopMenuGrid" Row="0" Column="0" ColumnSpan="2">
<menu1:MenuContainer x:Name="TopMenu"
MenuOrientation="Horizontal"
SelectedItem="{Binding MenuViewModel.SelectedHeaderMenuItem, Mode=TwoWay}"
MenuItems="{Binding MenuViewModel.HeaderMenuItems}"
SelectedTemplate="{StaticResource HeaderMenuSelectedItemTemplate}">
</menu1:MenuContainer>
</Grid>
<Grid Name="RightMenuGrid" Column="1" Row="1">
<menu1:MenuContainer x:Name="RightMenu"
MenuOrientation="Vertical"
SelectedItem="{Binding MenuViewModel.SelectedRightItem, Mode=TwoWay}"
MenuItems="{Binding MenuViewModel.RightMenuItems}"
SelectedTemplate="{StaticResource RightMenuSelectedItemTemplate}">
</menu1:MenuContainer>
</Grid>
<Grid Row="1" Name="ContentGrid" Column="0" ColumnSpan="1">
<TabControl Name="ContentTabControl"
SelectedIndex="{Binding MenuViewModel.SelectedPage}">
<TabItem Header="Home Page">
<TextBlock>Here comes the home page</TextBlock>
</TabItem>
</TabControl>
</Grid>
<Grid Name="DetailMenuGrid" Grid.Row="2" ColumnSpan="2" Column="0">
<menu1:MenuContainer Background="Aquamarine"
x:Name="BottomMenu" MenuOrientation="Horizontal"
SelectedItem="{Binding MenuViewModel.SelectedBottomItemItem, Mode=TwoWay}"
MenuItems="{Binding MenuViewModel.BottomMenuItems}"
SelectedTemplate="{StaticResource BottomMenuSelectedItemTemplate}">
</menu1:MenuContainer>
</Grid>
</Grid>
樣式:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp.Client.Resources"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:helpers="clr-namespace:MyApp.CommonGui.Helpers;assembly=MyApp.CommonGui">
<ControlTemplate x:Key="BottomMenuSelectedItemTemplate" TargetType="ListViewItem">
<Border SnapsToDevicePixels="true"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="5" x:Name="border"
>
<StackPanel>
<Popup PlacementTarget="{Binding ElementName=TextBlockContent}"
Child="{Binding SelectedControl}"
Width="{TemplateBinding Width}"
Placement="Top" VerticalOffset="-2" AllowsTransparency="True"
IsOpen="{Binding IsActive, Mode=TwoWay}">
<i:Interaction.Behaviors>
<helpers:AutoRepositionPopupBehavior/>
</i:Interaction.Behaviors>
</Popup>
<ContentControl
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="0,0,0,0"
VerticalAlignment="Center">
<Grid VerticalAlignment="Center">
<ToggleButton
Height="64"
BorderThickness="0"
Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"
VerticalAlignment="Bottom"
x:Name="TextBlockContent"
Content="{Binding Name}"
VerticalContentAlignment="Center"
IsChecked="{Binding IsActive}"
></ToggleButton>
</Grid>
</ContentControl>
</StackPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="HeaderMenuSelectedItemTemplate" TargetType="ListViewItem">
<Border SnapsToDevicePixels="true"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="5" x:Name="border"
>
<StackPanel>
<ContentControl
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="0,0,0,0"
VerticalAlignment="Center">
<Grid VerticalAlignment="Center">
<Grid>
<TextBlock x:Name="TextBlockContent" Text="{Binding
</Grid>
</Grid>
</ContentControl>
</StackPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="RightMenuSelectedItemTemplate" TargetType="ListViewItem">
<Border SnapsToDevicePixels="true"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="5" x:Name="border"
>
<StackPanel>
<ContentControl
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Margin="0,0,0,0"
VerticalAlignment="Center">
<Grid VerticalAlignment="Center">
<ToggleButton
Height="64"
BorderThickness="0"
Background="{Binding
RelativeSource={RelativeSource TemplatedParent},
Path=Background}"
VerticalAlignment="Bottom"
x:Name="TextBlockContent"
Content="{Binding Name}"
VerticalContentAlignment="Center"
IsChecked="{Binding IsActive}">
</ToggleButton>
</Grid>
</ContentControl>
</StackPanel>
</Border>
</ControlTemplate>
我希望通過這裏清楚地瞭解我的問題: 我需要知道如何進入MenuContainer用戶控件背後的代碼的SelectedTemplateChanged方法,以便設置ListView的選定項目的樣式。
但我相信這可以做得更優雅。我對「高級」xaml和模板樣式相當陌生,因此我陷入了一些困境。我已經搜索了幾個小時的論壇,試圖找到一個解決方案,但我還沒有成功。
是否有可能在沒有SelectedTemplateChanged後面的代碼的情況下實現這個功能?
任何幫助表示讚賞,直接解決我的問題或替代解決方案。
謝謝!這就是我需要的一切:) – yelbow