如何将动画绑定到用户控件

时间:2018-08-24 13:44:29

标签: c# wpf mvvm user-controls dependency-properties

我要达到的目标 enter image description here

代码在这里 https://hastebin.com/uqumowediq.xml

请注意如何利用RadioButton来跟踪属性以检查其正确与否。

但是,基于ListBox构建的UserControl并非如此, 使用我的ListBox,我希望能够以EntryItemViewModel的形式获得所选项目的数据,这很容易,我将更改Dependency属性的类型以将SelectedItem返回为EntryItemViewModel。

但是,我想像上面提供的gif一样滑出StackPanel,上面带有一个文本框,因此我可以将Title属性绑定到该文本框的Text属性。再次简单。

我的问题是.. 当我单击列表框中的项目时,我希望它将StackPanel滑到侧面。再次,就像上面的gif一样,当我选择另一个时,它会滑回,然后再次显示新数据,但这将是同一窗口。

我现在所拥有的就是这个。

我的UserControl

d:DesignHeight="300"
             d:DesignWidth="300"
             Height="535">
    <Grid Background="LightGray">
        <ListBox SelectionMode="Single" 
                 ItemsSource="{Binding Items}"
                 SelectedItem="{Binding SelectedItem}"
                 x:Name="TheListBox">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border Grid.Column="2" Padding="0,0,8,0">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <!-- Selected Item -->
                                <ColumnDefinition Width="Auto"/>
                                <!-- Image Item -->
                                <ColumnDefinition Width="Auto"/>
                                <!-- Main content-->
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <!-- Item image -->
                            <Border Grid.Column="1" Padding="8">
                                <Image Source="{Binding Image}"
                                       UseLayoutRounding="True"
                                       RenderOptions.BitmapScalingMode="Fant"
                                       Height="40"
                                       Width="40"/>
                            </Border>


                            <!-- Main Content -->
                            <Border Grid.Column="2" Padding="0,0,8,0">
                                <StackPanel VerticalAlignment="Center">
                                    <!-- Main Content -->
                                    <TextBlock Text="{Binding Title, FallbackValue=Title}"
                                               TextTrimming="CharacterEllipsis"
                                               FontWeight="Bold"/>

                                    <!-- Main Content -->
                                    <TextBlock Text="{Binding Username, FallbackValue=Username}"
                                               TextTrimming="CharacterEllipsis"/>
                                    <!-- Website URl -->
                                    <TextBlock Text="{Binding Password, FallbackValue=https://facebook.com}" Foreground="Gray"
                                               TextTrimming="CharacterEllipsis"/>
                                </StackPanel>
                            </Border>
                        </Grid>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>

            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <Border x:Name="Border"
                                        BorderBrush="Transparent"
                                        BorderThickness="5,0,0,0">
                                    <ContentPresenter Margin="0,0,0,0" />
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                        <Setter TargetName="Border" Property="BorderBrush" Value="LightSkyBlue" />
                                    </Trigger>


                                    <Trigger Property="IsSelected" Value="True">
                                        <Trigger.EnterActions>
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <DoubleAnimation
                                                        Storyboard.TargetProperty="Opacity"
                                                        From="0.0" To="1.0" Duration="0:0:1"/>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </Trigger.EnterActions>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
    </Grid>

后跟UserControls

public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }

        //Not sure what type this should be yet, I think this plays a big roll for this issue
        public bool SelectedItem
        {
            get { return (bool)GetValue(MyPropertyProperty); }
            set { SetValue(MyPropertyProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MyPropertyProperty =
            DependencyProperty.Register("SelectedItem", typeof(bool), typeof(MyUserControl));

    }

我在MainWindow中展示了UserControl,这就是我要存储将要滑出的StackPanel的地方,现在它只是一个立方体。

<Grid>
    <Grid.Resources>
        <system:Double x:Key="SlideOffSet">50</system:Double>
        <Storyboard x:Key="SlideRight">
            <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
                             From="0" To="{StaticResource SlideOffSet}"
                             Duration="0:0:0.2" />
        </Storyboard>
        <Storyboard x:Key="SlideLeft">
            <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
                             From="{StaticResource SlideOffSet}" To="0"
                             Duration="0:0:0.2" />
        </Storyboard>
    </Grid.Resources>

    <local:MyUserControl x:Name="UserControl"/>

    <StackPanel Width="100"
                Height="100"
                Background="Gray">

        <StackPanel.Style>
            <Style TargetType="StackPanel">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ElementName=UserControl, Path=SelectedItem}" Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource SlideRight}" />
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource SlideLeft}" />
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </StackPanel.Style>

        <StackPanel.RenderTransform>
            <TranslateTransform />
        </StackPanel.RenderTransform>

    </StackPanel>
</Grid>

对于EntryItemViewModel.cs,我们有这个

public class EntryItemViewModel : INotifyPropertyChanged
    {
        private string _title;

        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

最后但并非最不重要的AllEntriesViewModel.cs

public class AllEntriesListViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<EntryItemViewModel> Items { get; set; } = new ObservableCollection<EntryItemViewModel>();

        public EntryItemViewModel EntryItemViewModel { get; set; } = new EntryItemViewModel();

        public AllEntriesListViewModel()
        {
            Items.Add(new EntryItemViewModel { Title = "Hello World" });
            Items.Add(new EntryItemViewModel { Title = "Hello World1" });
            Items.Add(new EntryItemViewModel { Title = "Hello World2" });
            Items.Add(new EntryItemViewModel { Title = "Hello World3" });
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

DataContext设置为AllEntriesItemViewModel的新实例

0 个答案:

没有答案