Reputation: 1057
So I have a project with my own UserControl that is build around a ListBox
and I want to make it to where when I click a Item in the ListBox
,
I want my StackPanel
to slide to the right.
And when I click another item, the StackPanel
should slide back to where it started from and then slide out again.
This can be done using RadioButtons
but I am not sure if you can mix those in any way, because with RadioButtons
you can keep track of wether a item is selected by using a bool because the RadioButton
has the isChecked
property.
Making it to where.. If the RadioButton
is Checked it turns to true
and then the Animation
triggers on True
and when you click a new RadioButton
it turns to false
because the one you had selected is not selected anymore. But then true
again when you click a new one.
And the false
would obviously trigger the slide in animation.
So I guess I need to check if an item is selected in the ListBox so something like this maybe?
foreach(Item item in MyListBox.Items)
if(MyListBox.SelectedItems.Contains(item)
MyObject.Value = true;
else
MyObject.Value = false;
But using XAML ofcourse databainding it.
MainWindow.xaml
<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.IsSelected}" 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>
My UserControl
<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>
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));
}
}
AllEntriesListViewModel.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));
}
}
EDIT
I tried adding a Converter but it's still not reacting to me selecing a value
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if ((EntryItemViewModel)value != null)
{
return true;
}
else
{
return false;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
<DataTrigger Binding="{Binding ElementName=MyUserControl, Path=AllEntriesListViewModel.SelectedItem.IsSelected, Converter={StaticResource EntryModelConverter}}" Value="True">
If I put a breakpoint on the property, it gets the selected EntryViewModel but the animation isnt reacting
Upvotes: 0
Views: 68
Reputation: 1263
The reason your <DataTrigger Binding="{Binding ElementName=UserControl, Path=SelectedItem.IsSelected}" Value="True">
is not working as your UserControl does not have a property name SelectedItem. It is for the ListBox inside the UserControl.
You need to create a property "SelectedItem" in your ViewModel of UserControl (AllEntriesListViewModel) and bind SelectedItem to that property, and then if you use DataContext.SelectedItem <DataTrigger Binding="{Binding ElementName=UserControl, Path=DataContext.SelectedItem.IsSelected}" Value="True">
it would be able to access the property.
Edit:
You would also need to create one more boolean property IsSelected in the AllEntriesListViewModel, and change that property based on the SelectedItem change.
private EntryItemViewModel _selectedItem;
public EntryItemViewModel SelectedItem
{
get { return _selectedItem; }
set
{
if(_selectedItem != value)
{
_selectedItem = value;
IsSelected = !IsSelected;
OnPropertyChanged(nameof(SelectedItem));
}
}
}
and bind the data trigger to DataContext.IsSelected.
Upvotes: 2