I have a very simple ListView that has a dataTemplate, which is bound to a ObservableCollection in page code. I want to change the height of a single Item in listview as soon as it gets clicked.
This behaviour shopuld mimic the standard Mail and Wifi-Ui Windows 10 interfaces.
Possible Solution:- I have defined two datatemplate in Xaml as a resource and in a click event I am changing the ItemTemplateSelector property of listview. But the problem is that every item in listview changes itself to that datatemplate, which by the way makes sense. But this is not what I want to implement. I just want to change the height of a single item in listview when clicked maybe even with some animations.
Posssible Second Solution: I am defining just one datatemplate in my Xaml that contains a grid. Now what I am doing is binding height of grid to a public property in c# code. And in Itemclick event I am getting the e.ClickedItem and then changing the height of the property to something different. This is supposed to work but the value which is bound to Grid Height does changes but is not reflected in UI. Does it has somthing to do with {Bind statement}, do I need to use {x:Bind}?
I want to animate the transition between collapsed and expanded views.
You can have two data templates which share some UI, and one has some more elements than the other. The issue you will have is how to update to a different template on click on the fly.
I recently answered a question here which solves this issue by subscribing to the IsSelected
property and manually reset the ContentTemplateSelector
to force updating the template.
But swapping the full template to me is an overkill, and I lean towards your second solution too.
Looks like you are trying to update the Height
via a property in your ViewModel , this could work. But to me, this kind of UI logic is better put in the code-behind, where you can easily obtain your Grid
inside the ItemClick
callback and just assign a different Height
to it.
But then what if you needed a similar ListView
elsewhere with similar requirements? You'd end up with a lot of duplicate code-behind code. This is why I'd actually extend the ListViewItem
functionality to cater for expanding some parts of UI inside its ItemTemplate
. So here is how -
First, let's create an ExtendedListViewItem
that inherits from the ListViewItem
. This extended control does two things -
IsExpandable
which will later be attached to some UI element inside the ListView
's data template.ListViewItem
is clicked, the IsSelected
property gets updated, we can monitor it to show and hide the IsExpandable
element(s) accordingly.public class ExtendedListViewItem : ListViewItem
{
public ExtendedListViewItem()
{
// This could be set in its default style in Generic.xaml instead.
HorizontalContentAlignment = HorizontalAlignment.Stretch;
RegisterPropertyChangedCallback(IsSelectedProperty, (s, e) =>
{
// Children() is available at
// https://github.com/JustinXinLiu/Continuity/blob/0cc3d7556c747a060d40bae089b80eb845da84fa/Continuity/Extensions/UtilExtensions.cs#L25
foreach (var child in this.Children())
{
if (GetIsExpandable(child))
{
child.Visibility = IsSelected ? Visibility.Visible : Visibility.Collapsed;
}
}
});
}
public static void SetIsExpandable(DependencyObject element, bool value) =>
element.SetValue(IsExpandableProperty, value);
public static bool GetIsExpandable(DependencyObject element) =>
(bool)element.GetValue(IsExpandableProperty);
public static readonly DependencyProperty IsExpandableProperty = DependencyProperty.RegisterAttached(
"IsExpandable",
typeof(bool),
typeof(ExtendedListViewItem),
new PropertyMetadata(default(bool), (s, e) =>
{
var element = (UIElement)s;
element.Visibility = (bool)e.NewValue ? Visibility.Collapsed : Visibility.Visible;
}));
}
Next, we also need to extend the ListView
control to take our ExtendedListViewItem
control as its child instead of the default ListViewItem
.
public class ExtendedListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ExtendedListViewItem();
}
}
Finally, it's time to attach the IsExpandable
flag to the right element. For example, I only want the texts to show when the item is clicked -
<DataTemplate x:Key="MyItemTemplate">
<StackPanel Margin="24">
<Image HorizontalAlignment="Left" Source="{Binding Property3}" Width="48" Height="48" />
<StackPanel Margin="12" local:ExtendedListViewItem.IsExpandable="True">
<TextBlock Text="{Binding Property1}" Style="{StaticResource TitleTextBlockStyle}" />
<TextBlock Text="{Binding Property2}" Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</StackPanel>
</DataTemplate>
<local:ExtendedListView ContainerContentChanging="OnMyListViewContainerContentChanging"
ItemTemplate="{StaticResource MyItemTemplate}"
ItemsSource="{Binding Groups}" />
Noticed the ExtendedListView
control is subscribing to an event called ContainerContentChanging
? This is the place where you can create implicit offset animations for your items to make layout changes more interesting.
private void OnMyListViewContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
var containerVisual = ElementCompositionPreview.GetElementVisual(args.ItemContainer);
if (args.InRecycleQueue)
{
containerVisual.ImplicitAnimations = null;
}
else
{
// EnableImplicitAnimation() is available at
// https://github.com/JustinXinLiu/Continuity/blob/0015a96897c138e09d8604267df46da936b66838/Continuity/Extensions/CompositionExtensions.Implicit.cs#L144
containerVisual.EnableImplicitAnimation(VisualPropertyType.Offset, 400.0f);
}
}
Hope this helps!
Okay, sorry about that, I understand now. First of all you need to set the name and original height of the list view in your xaml.
<ListView x:Name="GenericName" height="x"></ListView>
Next, you want to have a code behind about the button being clicked. within this. you need to put in a statement that will set the height to a different value. It's actually pretty simple.
private void Button_Click (object sender, RoutedEventArgs e)
{
GenericName.Height = NewValue;
}
And that should work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.