这是我想要做的。我有一个非常简单的ListView,它具有一个dataTemplate,该模板绑定到页面代码中的ObservableCollection。很简单吧?现在,我想在单击列表时立即更改列表视图中单个项目的高度。
Windows的Mail和Wifi-Ui使用这种操纵。检查图像以更好地理解。
可能的解决方案:-我已经在Xaml中定义了两个数据模板作为资源,并且在单击事件中,我正在更改listview的ItemTemplateSelector属性。但是问题在于,列表视图中的每个项目都会将自身更改为该数据模板,这很有意义。但这不是我想要实现的。我只想更改单击列表视图中单个项目的高度,甚至在单击某些动画时也是如此。
可能的第二种解决方案:我在Xaml中仅定义一个包含网格的数据模板。现在我正在做的是将网格高度绑定到c#代码中的公共属性。在Itemclick事件中,我得到e.ClickedItem,然后将属性的高度更改为其他值。这应该可以工作,但是绑定到“网格高度”的值会更改,但不会反映在UI中。它与{Bind statement}有关系吗,我需要使用{x:Bind}吗?
enter image description here这是折叠后的版本的样子……
enter image description here这是扩展版本的外观,整个扩展过程都是通过动画进行的。
您可以有两个共享某些UI的数据模板,一个模板比另一个模板具有更多的元素。您将遇到的问题是如何快速单击以更新到其他模板。
我最近回答了一个问题here,该问题通过订阅IsSelected
属性来解决此问题,并手动重置ContentTemplateSelector
以强制更新模板。
但是将完整模板交换给我是一个过大的决定,我也倾向于您的第二个解决方案。
好像您正在尝试通过ViewModel中的属性更新Height
,这可能有效。但是对我来说,这种UI逻辑最好放在后面的代码中,您可以在Grid
回调中轻松获取ItemClick
并为其分配一个不同的Height
。
但是如果您在其他地方有类似要求的类似ListView
,该怎么办?您最终会得到很多重复的代码隐藏代码。这就是为什么我实际上要扩展ListViewItem
功能以适应在ItemTemplate
中扩展UI的某些部分的原因。所以这是-
首先,我们创建一个从ExtendedListViewItem
继承的ListViewItem
。此扩展控件有两件事-
IsExpandable
的附加属性,稍后会附加到ListView
数据内的某些UI元素模板。ListViewItem
时,IsSelected
属性都会更新,因此我们可以对其进行监视以相应地显示和隐藏IsExpandable
元素。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;
}));
}
接下来,我们还需要扩展ListView
控件以将我们的ExtendedListViewItem
控件作为其子级,而不是默认的ListViewItem
。
public class ExtendedListView : ListView
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ExtendedListViewItem();
}
}
最后,是时候将IsExpandable
标志附加到右侧元素了。例如,我只希望单击该项目时显示文本-
<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}" />
忽略ExtendedListView
控件正在订阅名为ContainerContentChanging
的事件吗?在这里可以为项目创建隐式偏移动画,以使布局更改更有趣。
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);
}
}
希望这会有所帮助!
[好,抱歉,我现在明白了。首先,您需要在xaml中设置列表视图的名称和原始高度。
<ListView x:Name="GenericName" height="x"></ListView>
[下一步,您想要在代码后面添加有关单击按钮的代码。在这个范围内。您需要输入一条声明,将高度设置为其他值。实际上很简单。
private void Button_Click (object sender, RoutedEventArgs e)
{
GenericName.Height = NewValue;
}
这应该起作用。