UWP ListView 拖放后更新行背景
UWP ListView Update Row Background After Drag and Drop
我目前这样做是为了使我的 ListView
具有交替行背景。
private void SongsListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (AlternatingRowColor)
args.ItemContainer.Background = args.ItemIndex % 2 == 0 ? Helper.WhiteSmokeBrush : Helper.WhiteBrush;
}
此外,我还允许 ListView
能够拖放项目。但是,即使我这样做,行颜色在删除后也不会更新其颜色:
private void SongsListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
sender.UpdateLayout(); // Refresh Row Color
}
意味着我的 ListView
在拖放后没有交替背景。
我应该如何更新它的背景?
ContainerContentChanging
为初始化渲染,UpdateLayout
用于保证元素已经渲染完成,而不是重新渲染整个列表。
对于您的情况,我建议使用IValueConverter
进行背景颜色转换。您可以向数据类型添加 Index
属性 以标识它现在的位置。
这是一个简单的例子:
TestModel.cs
public class TestIndex:INotifyPropertyChanged
{
private int _index;
public int Index
{
get => _index;
set
{
_index = value;
OnPropertyChanged();
}
}
// other properties
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
converter.cs
public class BackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if(value is int index)
{
// You can change color here.
if (index % 2 == 0)
return new SolidColorBrush(Colors.Red);
else
return new SolidColorBrush(Colors.Blue);
}
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
xaml
<Page ...>
<Page.Resources>
<local:BackgroundConverter x:Key="BackgroundConverter"/>
<DataTemplate x:Key="DefaultRow" x:DataType="local:TestIndex">
<Grid Background="{x:Bind Index,Converter={StaticResource BackgroundConverter}, Mode=OneWay}" Height="50">
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<ListView ItemsSource="{x:Bind TestCollection}"
IsItemClickEnabled="True"
AllowDrop="True"
CanReorderItems="True"
IsSwipeEnabled="True"
ItemTemplate="{StaticResource DefaultRow}"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Page>
xaml.cs
private ObservableCollection<TestIndex> TestCollection = new ObservableCollection<TestIndex>();
public ListViewPage()
{
this.InitializeComponent();
for (int i = 0; i < 10; i++)
{
TestCollection.Add(new TestIndex()
{
Index = i
});
}
TestCollection.CollectionChanged += CollectionChanged;
}
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
for (int i = 0; i < TestCollection.Count; i++)
{
TestCollection[i].Index = i;
}
}
这是因为在 ListView 中拖放项目时不会触发 DragItemsCompleted
事件。因为本质上是集合元素的删除和添加,所以需要为集合注册CollectionChanged
事件
此致。
一个更简单的解决方案是:
private void SongsListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
for(int i = 0; i < sender.Items.Count; i++)
{
var container = sender.ContainerFromIndex(i) as ListViewItem;
container.Background = i % 2 == 0 ? Helper.WhiteSmokeBrush : Helper.WhiteBrush;
}
}
我目前这样做是为了使我的 ListView
具有交替行背景。
private void SongsListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (AlternatingRowColor)
args.ItemContainer.Background = args.ItemIndex % 2 == 0 ? Helper.WhiteSmokeBrush : Helper.WhiteBrush;
}
此外,我还允许 ListView
能够拖放项目。但是,即使我这样做,行颜色在删除后也不会更新其颜色:
private void SongsListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
sender.UpdateLayout(); // Refresh Row Color
}
意味着我的 ListView
在拖放后没有交替背景。
我应该如何更新它的背景?
ContainerContentChanging
为初始化渲染,UpdateLayout
用于保证元素已经渲染完成,而不是重新渲染整个列表。
对于您的情况,我建议使用IValueConverter
进行背景颜色转换。您可以向数据类型添加 Index
属性 以标识它现在的位置。
这是一个简单的例子:
TestModel.cs
public class TestIndex:INotifyPropertyChanged
{
private int _index;
public int Index
{
get => _index;
set
{
_index = value;
OnPropertyChanged();
}
}
// other properties
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
converter.cs
public class BackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if(value is int index)
{
// You can change color here.
if (index % 2 == 0)
return new SolidColorBrush(Colors.Red);
else
return new SolidColorBrush(Colors.Blue);
}
return new SolidColorBrush(Colors.Red);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
xaml
<Page ...>
<Page.Resources>
<local:BackgroundConverter x:Key="BackgroundConverter"/>
<DataTemplate x:Key="DefaultRow" x:DataType="local:TestIndex">
<Grid Background="{x:Bind Index,Converter={StaticResource BackgroundConverter}, Mode=OneWay}" Height="50">
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<ListView ItemsSource="{x:Bind TestCollection}"
IsItemClickEnabled="True"
AllowDrop="True"
CanReorderItems="True"
IsSwipeEnabled="True"
ItemTemplate="{StaticResource DefaultRow}"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Page>
xaml.cs
private ObservableCollection<TestIndex> TestCollection = new ObservableCollection<TestIndex>();
public ListViewPage()
{
this.InitializeComponent();
for (int i = 0; i < 10; i++)
{
TestCollection.Add(new TestIndex()
{
Index = i
});
}
TestCollection.CollectionChanged += CollectionChanged;
}
private void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
for (int i = 0; i < TestCollection.Count; i++)
{
TestCollection[i].Index = i;
}
}
这是因为在 ListView 中拖放项目时不会触发 DragItemsCompleted
事件。因为本质上是集合元素的删除和添加,所以需要为集合注册CollectionChanged
事件
此致。
一个更简单的解决方案是:
private void SongsListView_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
{
for(int i = 0; i < sender.Items.Count; i++)
{
var container = sender.ContainerFromIndex(i) as ListViewItem;
container.Background = i % 2 == 0 ? Helper.WhiteSmokeBrush : Helper.WhiteBrush;
}
}