我正在尝试创建一个可以同时播放多个视频的视频播放器。我已经让玩家工作了,现在我试图让用户在运行时添加其他视频。我在统一网格中显示视频,该网格使用转换器根据视频数量决定应生成多少行和列。当你在运行之前定义有多少玩家时它可以正常工作,但是当我在运行时添加一个玩家时,统一网格不会更新行或列。它只是为之前的任何结构添加了另一个视频。反正我是否可以强制它重新评估行/列?
TL; DR:在查看统一网格时,我可以重新评估统一网格的行和列吗?怎么样?
控件的xaml如下。
可能有用的其他信息:
1.玩家是ObservableCollection
2.控件正在显示一个TabControl
<UserControl x:Class="Views.AllVideos"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-Views"
mc:Ignorable="d">
<ItemsControl ItemsSource="{Binding Players}"
x:Name="AllVideosControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding Players, Converter={StaticResource CountToColumns}, Mode=OneWay}"
Rows="{Binding Players, Converter={StaticResource CountToRows}, Mode=OneWay}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="1"
Margin="5">
<ls:PanelPreview DataContext="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
答案 0 :(得分:1)
根本不需要设置Rows
和Columns
。没有它们,一切都会奏效。 UniformGrid
会将所有内容统一放在任何容器内。
如果您仍想使用Binding
,那么以下方法适用于我,Cols
在此处已修复。 <{1}}不需要。
Converters
答案 1 :(得分:0)
问题似乎是没有任何东西通知绑定Players
中的项目数已经改变:Binding坐在那里等待你的viewmodel告诉它有一个新的Players
集合。
但由于Players
是ObservableCollection
,因此当PropertyChanged
更改时,它会引发Count
。所以,最简单的情况:
<UniformGrid
Rows="{Binding Players.Count}"
...
/>
以下内容适用于我在项目添加到Players
时更新行数和列数。转换器中的算法可以使用一些工作,但关键是每次UniformGrid.Rows
更改时绑定都会更新UniformGrid.Columns
和Players
。这是有效的,因为ObservableCollection
每次添加或删除项目时都会引发PropertyChanged("Count")
。因为我绑定到ObservableCollection
的属性,所以绑定会订阅ObservableCollection
的{{1}}事件,因此它知道在PropertyChanged
更改时更新。
C#
Count
XAML
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void AddButton_Click(object sender, RoutedEventArgs e)
{
(DataContext as ViewModel).Players.Add($"Player {(DataContext as ViewModel).Players.Count + 1}");
}
private void RemoveButton_Click(object sender, RoutedEventArgs e)
{
if ((DataContext as ViewModel).Players.Count > 0)
(DataContext as ViewModel).Players.RemoveAt(0);
}
}
public class ViewModel
{
private ObservableCollection<String> _players = new ObservableCollection<string>();
public ObservableCollection<String> Players
{
get { return _players; }
}
}
public class RowsColumnsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Math.Ceiling(Math.Sqrt((int)value));
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}