Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义控件x:类问题和动画_C#_Wpf_Xaml_Custom Controls - Fatal编程技术网

C# 自定义控件x:类问题和动画

C# 自定义控件x:类问题和动画,c#,wpf,xaml,custom-controls,C#,Wpf,Xaml,Custom Controls,我试图创建一个菜单自定义控件,其中包含一些动画,使事情看起来更“流畅”。这就是我遇到问题的地方,我希望自定义控件的宽度由动画驱动,以模拟菜单的扩展。我可以通过在模板中使用触发器来实现这一点,但使用这种方法,我似乎找不到绑定“to”的方法,我读到这是不允许的,因为线程安全,所以我想我应该只使用“Click”事件,并在代码后面制作动画 当我试图将我的类添加到资源字典时,我最终得到了一堆错误,在类文件中说“DefaultStyleKeyProperty”在当前上下文中不存在。我需要将我的类添加到资源字

我试图创建一个菜单自定义控件,其中包含一些动画,使事情看起来更“流畅”。这就是我遇到问题的地方,我希望自定义控件的宽度由动画驱动,以模拟菜单的扩展。我可以通过在模板中使用触发器来实现这一点,但使用这种方法,我似乎找不到绑定“to”的方法,我读到这是不允许的,因为线程安全,所以我想我应该只使用“Click”事件,并在代码后面制作动画

当我试图将我的类添加到资源字典时,我最终得到了一堆错误,在类文件中说“DefaultStyleKeyProperty”在当前上下文中不存在。我需要将我的类添加到资源字典中,以便能够访问任何UI对象。所以我有点被困在如何实现这一点上,还是我走错了方向

以下是我到目前为止的情况:

NavMenu.xaml Generic.xaml

我尝试将xClass添加到Generic.xaml中,但也没有成功,当我这样做时,我收到了另一个错误:“NavMenu的部分声明不能指定不同的基类”

编辑
我知道必须有一个更好的方法来做到这一点,使用互动库。我最后做的是专门为动画创建一个新类。然后我可以将新的TriggerAction附加到我的控件上,我发现我需要为目标动画元素提供一个ListContainer。这是因为无法实现从0到“自动”的动画,面板提供了一种获取子对象并在代码中计算“自动”宽度的方法。以下是我的更新:

NavMenu.cs
namespace Happ.UI.Controls{
公共类导航菜单:菜单{
静态导航菜单(){
DefaultStyleKeyProperty.OverrideMetadata(typeof(NavMenu)),new FrameworkPropertyMetadata(typeof(NavMenu));
}
/// 
///指示菜单是否展开的标志
/// 
公共图书馆被扩展了{
得到{
返回(bool)GetValue(IsExpandedProperty);
}
设置{
SetValue(IsExpandedProperty,值);
}
}
公共静态只读从属属性IsExpandedProperty=
DependencyProperty.Register(“IsExpanded”、typeof(bool)、typeof(NavMenu)、new PropertyMetadata(true));
}
}
NavMenu.Animations.cs
namespace Happ.UI.Controls{
公共类导航设置:System.Windows.Interactivity.TriggerAction{
/// 
///设置动画的目标元素
/// 
公众小组目标小组{
得到{
返回(面板)GetValue(TargetPanelProperty);
}
设置{
SetValue(TargetPanelProperty,value);
}
}
公共静态只读DependencyProperty TargetPanelProperty=
从属属性寄存器(“TargetPanel”、类型of(Panel)、类型of(NavMenuAnimations),
新属性元数据(空);
/// 
///设置动画的目标元素
/// 
公共双秒{
得到{
返回(双精度)GetValue(SecondsProperty);
}
设置{
设置值(第二属性,值);
}
}
公共静态只读从属属性SecondsProperty=
从属属性寄存器(“秒”、typeof(双精度)、typeof(导航状态),
新的房地产数据((双)0.5);
/// 
///这是每次触发时调用的主要动画方法
/// 
/// 
受保护的覆盖无效调用(对象参数){
双最大宽度=0;
//确保我们有一个目标元素
如果(TargetPanel==null){
抛出新异常(“没有为动画指定目标元素。(NavMenu动画)”;
}
//确保设置了最小宽度和高度
TargetPanel.MinWidth=(宽度>0)?宽度:TargetPanel.MinWidth;
//检查是否已设置MaxWidth
if(Double.IsInfinity(TargetPanel.MaxWidth)){
//在孩子们中间绕一圈,得到宽度
foreach(TargetPanel.Children中的UIElement元素){
//更新面板的最大宽度
maxWidth+=elem.RenderSize.Width;
}
//检查是否找到MaxWidth。如果未找到,则返回
如果(maxWidth==0)
返回;
//指定新的MaxWidth
TargetPanel.MaxWidth=MaxWidth;
}
//检查宽度是否为最小值(收缩)
if(TargetPanel.Width==TargetPanel.MinWidth){
BeginAnimation(FrameworkElement.WidthProperty,新的DoubleAnimation(TargetPanel.MaxWidth,TimeSpan.FromSeconds(秒));
}
否则{
BeginAnimation(FrameworkElement.WidthProperty,新的DoubleAnimation(TargetPanel.MinWidth,TimeSpan.FromSeconds(秒));
}
}
}
}
NavMenuTemplate.xaml

<ResourceDictionary x:Class="Happ.UI.Controls.NavMenu"
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Happ.UI.Controls">

    <Style TargetType="{x:Type local:NavMenu}">
            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <StackPanel Background="Yellow" Orientation="Vertical"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:NavMenu}">
                        <Border Background="{TemplateBinding Background}" BorderBrush="Transparent">
                        <ToggleButton x:Name="btnMenu" 
                                      Margin="10" Padding="4" Background="Transparent"
                                      HorizontalAlignment="Left" VerticalAlignment="Top"
                                      IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:NavMenu}}, Path=IsExpanded}" />
                        </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>
namespace Happ.UI.Controls {

    public partial class NavMenu : Menu {

        static NavMenu() {
            DefaultStyleKeyProperty.OverrideMetadata( typeof( NavMenu ), new FrameworkPropertyMetadata( typeof( NavMenu ) ) );
        }

        public bool IsExpanded {
            get {
                return (bool)GetValue( IsExpandedProperty );
            }
            set {
                TimeSpan tsTime = new TimeSpan( 0, 0, 0, 0, 500 );
                DoubleAnimation mnuAnim = new DoubleAnimation( MinWidth, tsTime );
                btnMenu.BeginAnimation( Width, mnuAnim );
                SetValue( IsExpandedProperty, value );
            }
        }

        public static readonly DependencyProperty IsExpandedProperty =
             DependencyProperty.Register( "IsExpanded", typeof( bool ), typeof( NavMenu ), new PropertyMetadata( true ) );
        }
    }
}
<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Happ.UI.Controls">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/Happ.UI.Controls;component/Templates/NavMenu.xaml" />
    </ResourceDictionary.MergedDictionaries>



</ResourceDictionary>
namespace Happ.UI.Controls {

    public class NavMenu : Menu {

        static NavMenu() {
            DefaultStyleKeyProperty.OverrideMetadata( typeof( NavMenu ), new FrameworkPropertyMetadata( typeof( NavMenu ) ) );
        }

        /// <summary>
        /// Flag to Tell if the Menu is Expanded
        /// </summary>
        public bool IsExpanded {
            get {
                return (bool)GetValue( IsExpandedProperty );
            }
            set {
                SetValue( IsExpandedProperty, value );
            }
        }

        public static readonly DependencyProperty IsExpandedProperty =
             DependencyProperty.Register( "IsExpanded", typeof( bool ), typeof( NavMenu ), new PropertyMetadata( true ) );
    }
}
namespace Happ.UI.Controls {

    public class NavMenuAnimations : System.Windows.Interactivity.TriggerAction<UIElement> {

        /// <summary>
        /// Sets the Target Element for the Animation
        /// </summary>
        public Panel TargetPanel {
            get {
                return (Panel)GetValue( TargetPanelProperty );
            }
            set {
                SetValue( TargetPanelProperty, value );
            }
        }

        public static readonly DependencyProperty TargetPanelProperty =
            DependencyProperty.Register( "TargetPanel", typeof( Panel ), typeof( NavMenuAnimations ),
            new PropertyMetadata( null ) );

        /// <summary>
        /// Sets the Target Element for the Animation
        /// </summary>
        public double Seconds {
            get {
                return (double)GetValue( SecondsProperty );
            }
            set {
                SetValue( SecondsProperty, value );
            }
        }

        public static readonly DependencyProperty SecondsProperty =
            DependencyProperty.Register( "Seconds", typeof( double ), typeof( NavMenuAnimations ),
            new PropertyMetadata( (double)0.5 ) );

        /// <summary>
        /// This is the Main Animation Method that is called each time the Trigger occurs
        /// </summary>
        /// <param name="parameter"></param>
        protected override void Invoke( object parameter ) {
            double maxWidth = 0;

            //Make sure that we have a Target Element
            if( TargetPanel == null ) {
                throw new Exception( "No Target Element specified for the animation. (NavMenu Animations)" );
            }

            //Make sure the Min Width and Height are Set
            TargetPanel.MinWidth = ( Width > 0 ) ? Width : TargetPanel.MinWidth;


            //Check if the MaxWidth has been set
            if( Double.IsInfinity( TargetPanel.MaxWidth ) ) {

                //Loop through the Children and Get Width
                foreach( UIElement elem in TargetPanel.Children ) {

                    //Update the Max Width of the Panel
                    maxWidth += elem.RenderSize.Width;
                }

                //Check if we found a MaxWidth. if not return
                if( maxWidth == 0 )
                    return;

                //Assign the new MaxWidth
                TargetPanel.MaxWidth = maxWidth;
            }

            //Check if Width is at Minumum (Shrunk)
            if( TargetPanel.Width == TargetPanel.MinWidth ) {

                TargetPanel.BeginAnimation( FrameworkElement.WidthProperty, new DoubleAnimation( TargetPanel.MaxWidth, TimeSpan.FromSeconds( Seconds ) ) );
            }
            else {

                TargetPanel.BeginAnimation( FrameworkElement.WidthProperty, new DoubleAnimation( TargetPanel.MinWidth, TimeSpan.FromSeconds( Seconds ) ) );
            }


        }

    }
}
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
                    xmlns:local="clr-namespace:Happ.UI.Controls">

    <Style TargetType="{x:Type local:NavMenu}">
        <Setter Property="Width" Value="50"/>
        <Setter Property="Padding" Value="10" />
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <StackPanel x:Name="navMenu" Orientation="Vertical">

                    </StackPanel>
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:NavMenu}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="Transparent"
                            Padding="{TemplateBinding Padding}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Viewbox Grid.Row="0"
                                     HorizontalAlignment="Left" VerticalAlignment="Top"
                                     Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:NavMenu}}, Path=IconSize}"
                                     Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:NavMenu}}, Path=IconSize}">
                                <ToggleButton x:Name="btnMenu" Grid.Row="0" 
                                              Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:NavMenu}}, Path=MenuIcon}"
                                              Background="Transparent"
                                              Padding="0"
                                              IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:NavMenu}}, Path=IsExpanded}">
                                </ToggleButton>
                            </Viewbox>
                            <ItemsPresenter Grid.Row="1" MinWidth="50">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger SourceName="btnMenu" EventName="Click" >
                                        <local:NavMenuAnimations TargetPanel="{Binding ElementName=navMenu}"  Technique="ExpandWidth" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </ItemsPresenter>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
public class NavMenu : Menu
{
    static NavMenu()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NavMenu), new FrameworkPropertyMetadata(typeof(NavMenu)));
    }

    public bool IsExpanded
    {
        get
        {
            return (bool)GetValue(IsExpandedProperty);
        }
        set
        {
            SetValue(IsExpandedProperty, value);
        }
    }

    public static readonly DependencyProperty IsExpandedProperty =
         DependencyProperty.Register("IsExpanded", typeof(bool), typeof(NavMenu), new PropertyMetadata(true));

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        System.Windows.Controls.Primitives.ToggleButton btnMenu = Template.FindName("btnMenu", this) as System.Windows.Controls.Primitives.ToggleButton;
        TimeSpan tsTime = new TimeSpan(0, 0, 0, 0, 500);
        DoubleAnimation mnuAnim = new DoubleAnimation(0.0, MinWidth, tsTime);
        btnMenu.BeginAnimation(WidthProperty, mnuAnim);
    }
}