1

Non MVVM. Je suis arrivé ce ObservableCollection machines qui est fait de Machine objets -type:postsharp observablecollection tir collectionchangé sur propriétéchanged

[Serializable] 
[NotifyPropertyChanged] 
public abstract class Machine 
{ 
    public MachineNames MachineType { get; set; } 
    public int MachineVersion { get; set; } 
    public string LatestEditorName { get; set; } 
    public DateTime LatestSaveTime { get; set; } 

    public ObservableCollection<Parameter> Parameters { get; set; } 
    public string Notes { get; set; } 

    public abstract double CalculateThroughPut(); 

    public Machine() 
    { 
     string[] nameParts = this.GetType().Name.Split('_'); 
     Enum.TryParse(nameParts[0], out MachineNames currentMachineType); 
     MachineType = currentMachineType; 
     MachineVersion = int.Parse(nameParts[1]); 

     Parameters = new ObservableCollection<Parameter>(); 
     ICollectionView icv = CollectionViewSource.GetDefaultView(Parameters); 
     icv.GroupDescriptions.Add(new PropertyGroupDescription("Group")); 


     LatestEditorName = Environment.UserName; 
     LatestSaveTime = DateTime.Now; 
    } 

    public double getValue(string parameterName) 
    { 
     Parameter currentParameter = Parameters.Where(x => x.Name == parameterName).First(); 
     return currentParameter.Value * currentParameter.MetricConversionFactor; 
    } 

Et voici la déclaration de celui-ci:

public partial class MainWindow : MetroWindow 
{ 
    IEnumerable<string> namesOfExistingMachines { get; set; } 

    public ObservableCollection<Machine> machines { get; set; } 

et plus tard:

private void InitializeData() 
    { 
     machines = new ObservableCollection<Machine>(); 
     this.DataContext = machines; 

     tcMainTabControl.ItemsSource = machines; 

Avis s'il vous plaît la [NotifyPropertyChanged] tag qui fait partie de PostSharp, et rend simplement toutes les propriétés de Machine changenotifiable pour contraignant. en outre il fait toutes les propriétés des propriétés changenotifiable.

est ici la partie initiale de la fenêtre du XAML:

<Grid> 
    <Controls:MetroAnimatedTabControl Name="tcMainTabControl"> 
     <TabControl.ItemContainerStyle> 
      <Style TargetType="TabItem"> 
       <Setter Property="ToolTipService.ShowDuration" Value="100000"/> 
       <Setter Property="ToolTipService.InitialShowDelay" Value="0"/> 
       <Setter Property="Header" Value="{Binding Converter={StaticResource tabHeaderConverter}}"/> 
       <Setter Property="ToolTip"> 
        <Setter.Value> 
         <StackPanel Orientation="Vertical"> 
          <TextBlock HorizontalAlignment="Center" Margin="0,10" FontSize="40" FontWeight="Bold" Text="{Binding Path=MachineType}"/> 
          <Image HorizontalAlignment="Center" Source="{Binding Path=MachineType, Converter={StaticResource imageUriConverter}}"/> 
          <StackPanel HorizontalAlignment="Center" Margin="0,10" Orientation="Horizontal"> 
           <TextBlock FontSize="20" Text="Throughput model version "/> 
           <TextBlock FontSize="20" Text="{Binding Path=MachineVersion}"/> 
          </StackPanel> 
          <StackPanel HorizontalAlignment="Center" Margin="0,10" Orientation="Horizontal"> 
           <TextBlock FontSize="20" Text="created by "/> 
           <TextBlock FontSize="20" Text="{Binding Path=LatestEditorName}"/> 
           <TextBlock FontSize="20" Text=" on "/> 
           <TextBlock FontSize="20" Text="{Binding Path=LatestSaveTime, StringFormat=dd/MM/yyyy}"/> 
          </StackPanel> 
          <TextBlock Margin="0,10" FontSize="20" Text="{Binding Path=Notes}"/> 
         </StackPanel> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </TabControl.ItemContainerStyle> 
     <Controls:MetroAnimatedTabControl.ContentTemplate> 
      <DataTemplate> 
       <DockPanel LastChildFill="True" Margin="10,0"> 
        <StackPanel Orientation="Vertical"> 
         <Border BorderBrush="{DynamicResource AccentColorBrush}" BorderThickness="1,1,1,1" CornerRadius="8,8,8,8" Margin="0,20" HorizontalAlignment="Center"> 
          <StackPanel Orientation="Horizontal" Margin="5"> 
           <TextBlock FontSize="20" Text="Throughput: "/> 
           <TextBlock FontSize="20" Text="{Binding Converter={StaticResource throughputCalculationConverter}, UpdateSourceTrigger=PropertyChanged}"/> 
           <TextBlock FontSize="20" Text=" panel sides per hour"/> 
          </StackPanel> 
         </Border> 
         <ListView DockPanel.Dock="Left" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding Path=Parameters, UpdateSourceTrigger=PropertyChanged}"> 
          <ListView.GroupStyle> 
           <GroupStyle> 
            <GroupStyle.ContainerStyle> 
             <Style TargetType="{x:Type GroupItem}"> 
              <Setter Property="Margin" Value="0,0,0,5"/> 
              <Setter Property="Template"> 
               <Setter.Value> 
                <ControlTemplate TargetType="{x:Type GroupItem}"> 
                 <Expander IsExpanded="True" BorderBrush="Black" BorderThickness="0,0,0,1"> 
                  <Expander.Header> 
                   <TextBlock FontSize="20" FontWeight="Bold"> 
                   <Run>Discipline: </Run> 
                   <TextBlock Text="{Binding Path=Name, Converter={StaticResource titleCaseConverter}}"/> 
                  </TextBlock> 
                  </Expander.Header> 
                  <Expander.Content> 
                   <Border Margin="2" CornerRadius="3"> 
                    <ItemsPresenter /> 
                   </Border> 
                  </Expander.Content> 
                 </Expander> 
                </ControlTemplate> 
               </Setter.Value> 
              </Setter> 
             </Style> 
            </GroupStyle.ContainerStyle> 
           </GroupStyle> 
          </ListView.GroupStyle> 
          <ListView.ItemTemplate> 
           <DataTemplate> 
            <WrapPanel> 
             <TextBlock FontSize="20" Text="{Binding Name}" Margin="0,0,10,0" VerticalAlignment="Center"/> 
             <TextBox FontSize="20" BorderBrush="Black" BorderThickness="0,0,0,1" Background="Transparent" Controls:TextBoxHelper.Watermark="Enter value" Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Margin="0,0,10,0" VerticalAlignment="Center" HorizontalContentAlignment="Center"/> 
             <TextBlock FontSize="20" Text="{Binding Unit}" VerticalAlignment="Center"/> 
            </WrapPanel> 
           </DataTemplate> 
          </ListView.ItemTemplate> 
          <ListView.ItemContainerStyle> 
           <Style TargetType="{x:Type ListViewItem}"> 
            <Setter Property="ToolTip" Value="{Binding Path=Notes}"/> 
            <Setter Property="Background" Value="Transparent" /> 
            <Setter Property="Template"> 
             <Setter.Value> 
              <ControlTemplate TargetType="{x:Type ListViewItem}"> 
               <ContentPresenter /> 
              </ControlTemplate> 
             </Setter.Value> 
            </Setter> 
           </Style> 
          </ListView.ItemContainerStyle> 
         </ListView> 
        </StackPanel> 

Tout est OK dans le département de liaison. Ce que je voudrais, c'est invoquer l'événement CollectionChanged (ou quelque chose comme ça) pour machines chaque fois qu'une propriété à l'intérieur de l'un de ses membres Machine change la propriété en interne. Autrement dit: si je change, par exemple, un Parameter intérieur Parameters dans l'un des Machine s de machine, je voudrais à mettre à jour le calcul sur

<TextBlock FontSize="20" Text="{Binding Converter={StaticResource throughputCalculationConverter}, UpdateSourceTrigger=PropertyChanged}"/>

Merci!

Répondre

1

Pour propager les notifications PropertyChanged à partir des éléments de la collection, vous avez besoin de la classe de collection qui est abonnée aux notifications de modification de ses éléments. La classe standard ObservableCollection<T> ne le fait pas. Vous pouvez étendre le ObservableCollection<T> comme indiqué ci-dessous. Vous pouvez également trouver des exemples plus similaires sur SO (par exemple ObservableCollection that also monitors changes on the elements in collection). Lorsque vous utilisez cette classe de collection personnalisée, la collection déclenche un événement lorsqu'une propriété d'un élément est modifiée. Vous pouvez maintenant également demander à PostSharp de propager cette notification en tant que modification de la propriété de collection elle-même à l'aide de l'attribut [AggregateAllChanges] appliqué à la propriété de collection (par exemple Parameters, machines).

[AggregateAllChanges] 
public ObservableCollectionEx<Parameter> Parameters { get; set; } 

[AggregateAllChanges] 
public ObservableCollectionEx<Machine> machines { get; set; } 
+0

Merci! fonctionne très bien. – zazkapulsk