2016-04-23 9 views
1

Ich versuche, einen Videoplayer zu erstellen, der mehrere Videos gleichzeitig wiedergeben kann. Ich habe Spieler dazu gebracht zu arbeiten und jetzt versuche ich einem Nutzer zu erlauben, zur Laufzeit zusätzliche Videos hinzuzufügen. Ich zeige Videos in einem einheitlichen Raster an, das anhand eines Konverters entscheidet, wie viele Zeilen und Spalten basierend auf der Anzahl der Videos generiert werden sollen. Es funktioniert gut, wenn Sie definieren, wie viele Spieler vor dem Ausführen vorhanden sind. Wenn ich jedoch einen Player hinzufüge, während er ausgeführt wird, aktualisiert das einheitliche Raster die Zeilen oder Spalten nicht. Es fügt einfach ein anderes Video zu der Struktur hinzu, die es zuvor hatte. Gibt es trotzdem, dass ich es zwingen kann, die Zeilen/Spalten neu zu bewerten?Neubewertung von UniformGrid-Zeilen und -Spalten WPF

TL; DR: Kann ich die Zeilen und Spalten eines gleichmäßigen Gitters bei der Anzeige neu berechnen? Wie ?

Die XAML für die Kontrolle ist unten. Weitere Informationen Benutzer die hilfreich sein könnten:
1. Spieler ist ein ObservableCollection
2. Die Steuerung mit einem 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

http://stackoverflow.com/questions/15178726/setting-rows-of-itempaneltemplate-uniformgrid-through-c-sharp – StepUp

+0

Sind Sie 'Property ("Spieler")' jedes Mal, wenn die Anhebung * Zahl * von Spielern ändert sich? Weil dort nichts für mich sichtbar ist, um diese Bindungen zu aktualisieren, wenn sich die Anzahl ändert. Wenn Sie CountToColumns und CountToRows so umschreiben können, dass sie einen Int enthalten, können Sie auch einfach '{Binding Items.Count, RelativeSource = {RelativeSource Self}}, Converter = {StaticResource CountToColumns}}' verwenden. –

+0

Eigentlich scratchen: Ich habe es gerade getestet und 'Rows =" {Binding Players.Count} 'funktioniert perfekt für mich - wenn' Player' eine 'ObservableCollection' ist. Ist es? Wenn das der Fall ist, würde ich diese Konverter einfach neu schreiben, um Players.Count zu nehmen, modulo und fertig. –

Antwort

0

Das Problem zu sein scheint präsentiert wird, dass nichts die Bindung wird darüber informiert, dass die Zahl der Artikel in Players hat sich geändert: Die Bindung sitzt dort warten auf Ihr Viewmodel zu sagen, es gibt eine neue Players Sammlung.

Aber da Players ist ein ObservableCollection, es PropertyChanged erhöhen würde, wenn es Count Änderungen ist. So einfachsten Fall:

<UniformGrid 
    Rows="{Binding Players.Count}" 
    ... 
    /> 

Die folgenden Werke für mich die Zeilen- und Spaltenzahl zu aktualisieren, da Elemente Players hinzugefügt werden. Die Arithmetik im Konverter könnte ein wenig Arbeit gebrauchen, aber der Punkt ist, dass sich die Bindungen UniformGrid.Rows und UniformGrid.Columns jedes Mal ändern, wenn sich Players ändert. Dies funktioniert, weil ObservableCollectionPropertyChanged("Count") jedes Mal erhöht, wenn ein Element hinzugefügt oder entfernt wird. Da ich an eine Eigenschaft von ObservableCollection gebunden bin, abonniert die Bindung das ObservableCollectionPropertyChanged Ereignis, so dass es aktualisiert werden kann, wenn Count ändert.

C#

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(); 
    } 
} 

XAML

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 

    <ItemsControl 
     Grid.Row="1" 
     ItemsSource="{Binding Players}" 
     > 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <UniformGrid 
        Rows="{Binding Players.Count, Converter={StaticResource RowsColumns}}" 
        Columns="{Binding Players.Count, Converter={StaticResource RowsColumns}}" 
        /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 

    <StackPanel Grid.Row="0" Orientation="Horizontal"> 
     <Button 
      Content="Add Player" 
      Click="AddButton_Click" 
      Margin="2" 
      Width="100" 
      /> 
     <Button 
      Content="Remove Player" 
      Click="RemoveButton_Click" 
      Margin="2" 
      Width="100" 
      /> 
    </StackPanel> 
</Grid> 
+0

Ich denke, ich hätte erwähnen sollen, dass Players eine ObservableCollection ist, und dass es definitiv über die Bindung aktualisiert wird, da ich mehr Spieler zeige, es ist nur das Layout falsch –

+0

@ScottMaher Du hast gesagt, du hast Gegenstände im Gitter gesehen, also dachte ich, das war wahrscheinlich der Fall. –

+0

Hey Ed, Ihr Kommentar, der darauf hindeutet, dass ich direkt zu zählen gebunden bin, arbeitete wie ein Charme. Wenn du deine Antwort editierst, um sie aufzunehmen, akzeptiere ich deine Antwort :) –

1

Einstellung Rows und Columns wird nicht benötigt. Alles wird ohne sie auch funktionieren. UniformGrid wird alles gleichmäßig in welchen Behälter legen.

Wenn Sie immer noch Binding verwenden möchten, dann sind folgende Arbeiten für mich, Cols, hier behoben. Converters sind nicht erforderlich.

void Players_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     Rows = (int)Math.Ceiling(Players.Count/Cols); 
    }