Wpf 以使用ContentPresenter显示的Xaml中的嵌套内容为目标
考虑以下usercontrol: 这是我编写的自定义usercontrol,它有两个嵌套元素 FilterContent显示一种特殊类型的标记,用于过滤屏幕右侧的内容 MainContent承载过滤后的内容 控件的唯一真正用途是在整个应用程序中提供一致的UI和动画,因为经常使用此过滤器/内容模式 usercontrol的(简化的)Xaml如下所示:Wpf 以使用ContentPresenter显示的Xaml中的嵌套内容为目标,wpf,xaml,winrt-xaml,Wpf,Xaml,Winrt Xaml,考虑以下usercontrol: 这是我编写的自定义usercontrol,它有两个嵌套元素 FilterContent显示一种特殊类型的标记,用于过滤屏幕右侧的内容 MainContent承载过滤后的内容 控件的唯一真正用途是在整个应用程序中提供一致的UI和动画,因为经常使用此过滤器/内容模式 usercontrol的(简化的)Xaml如下所示: <UserControl> <Grid> <Grid.ColumnDefinitions&g
<UserControl>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="7*"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" Content="{Binding ElementName=filterControl, Path=FilterControl}" DataContext="{Binding}" />
<ContentPresenter Grid.Column="1" Content="{Binding ElementName=filterControl, Path=MainControl}" DataContext="{Binding}" />
</Grid>
控件在实现页中的用法是:
<Generic:FilterPaneControl>
<Generic:FilterPaneControl.FilterControl>
<Grid>
<TextBlock Text="Filter Content here"/>
</Grid>
</Generic:FilterPaneControl.FilterControl>
<Generic:FilterPaneControl.MainControl>
<Grid>
<TextBlock Text="Main Content here"/>
</Grid>
</Generic:FilterPaneControl.MainControl>
</Generic:FilterPaneControl>
那很好
问题
问题是当我想从实现页面引用控件中的一些内容时。处理快照/纵向(WinRT实现)的可视状态就是一个很好的例子
这会导致运行时异常,因为visualstatemanager无法找到引用的元素“filterContent1”,即使它存在于可视化树中。
此外,如果我尝试直接在Page.Loaded事件处理程序中引用该元素,则filterContent1为null
这就好像嵌套的Xaml直到稍后才渲染一样——这也会抛出visualstatemanager
有什么建议吗 首先,
VisualStateManager
应与执行该操作的元素放在一个面板中,否则将是一个例外。对于您的情况,结果如下:
<Generic:FilterPaneControl>
<Generic:FilterPaneControl.FilterControl>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="filterContent1" Text="Filter Content here"/>
</Grid>
</Generic:FilterPaneControl.FilterControl>
...
第三,在某种程度上:
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
为了证明他的话,我举了一个例子:
main窗口
<Window x:Class="VSMinUserControlHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VSMinUserControlHelp"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<local:UserControl1 x:Name="Control1" Height="118" VerticalAlignment="Top" Margin="50,12,101,0" />
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Name="State1Button" Width="75" Click="State1Button_Click">State1</Button>
</StackPanel>
</Grid>
</Window>
UserControl
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void State1Button_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(Control1, "State1", true);
}
}
<UserControl x:Class="VSMinUserControlHelp.UserControl1"
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:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Common1">
<VisualState x:Name="State1">
<Storyboard Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DoubleAnimation To="200" Duration="0:0:1.0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="filterContent1" Background="Aqua" Width="100" HorizontalAlignment="Left" Text="Filter Content here"/>
</Grid>
</UserControl>
注意:
在VS 2010、Windows XP上运行的示例,未在WinRT下测试。首先,VisualStateManager
应与要执行此操作的元素放在一个面板中,否则将是一个例外。对于您的情况,结果如下:
<Generic:FilterPaneControl>
<Generic:FilterPaneControl.FilterControl>
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualState x:Name="FullScreenPortrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="filterContent1" Text="Filter Content here"/>
</Grid>
</Generic:FilterPaneControl.FilterControl>
...
第三,在某种程度上:
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DiscreteObjectKeyFrame KeyTime="0" Value="200"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
为了证明他的话,我举了一个例子:
main窗口
<Window x:Class="VSMinUserControlHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VSMinUserControlHelp"
Title="MainWindow" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<local:UserControl1 x:Name="Control1" Height="118" VerticalAlignment="Top" Margin="50,12,101,0" />
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Name="State1Button" Width="75" Click="State1Button_Click">State1</Button>
</StackPanel>
</Grid>
</Window>
UserControl
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void State1Button_Click(object sender, RoutedEventArgs e)
{
VisualStateManager.GoToState(Control1, "State1", true);
}
}
<UserControl x:Class="VSMinUserControlHelp.UserControl1"
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:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Common1">
<VisualState x:Name="State1">
<Storyboard Storyboard.TargetName="filterContent1" Storyboard.TargetProperty="Width">
<DoubleAnimation To="200" Duration="0:0:1.0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="filterContent1" Background="Aqua" Width="100" HorizontalAlignment="Left" Text="Filter Content here"/>
</Grid>
</UserControl>
注意:
示例在VS 2010、Windows XP上运行,未在WinRT下测试。感谢您的回复。我以前考虑过您的解决方案,但不愿意实施,因为尽管它可能解决VisualStateManager问题,但在我希望从父容器引用子内容中的元素时,它仍然无法解决其他情况。(引用Page.Load中的子元素为null!)今天我将尝试至少尝试解决VSM问题。感谢您的回复。我以前考虑过您的解决方案,但不愿意实施,因为尽管它可能解决VisualStateManager问题,但在我希望从父容器引用子内容中的元素时,它仍然无法解决其他情况。(引用Page.Load中的子元素为null!)不过,今天我将尝试至少解决VSM问题。