none
wpf InvalidOperationException (treeview and listview mvvm) RRS feed

  • 问题

  • I have learnt wpf for about one month,and now I am writting something that get data from sqlserver and show it by wpf programme.

    My main window consists of two parts. treeview on the left and listview on the right.

    here's my code:

     <TreeView Name="nowtree" Margin="3" BorderThickness="0" ItemsSource="{Binding RootChild}" 
            VirtualizingStackPanel.IsVirtualizing="True"
       VirtualizingStackPanel.VirtualizationMode="Recycling" 
           >
          <TreeView.ItemContainerStyle>
           <!-- 
      This Style binds a TreeViewItem to a TreeViewItemViewModel. 
      -->
           <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
            <Setter Property="FontWeight" Value="Normal" />
            <Style.Triggers>
              <Trigger Property="IsSelected" Value="True">
              <Setter Property="FontWeight" Value="Bold" />
              <Setter Property="BitmapEffect">
               <Setter.Value>
                <OuterGlowBitmapEffect GlowColor="Yellow" />
               </Setter.Value>
              </Setter>
              <Setter Property="Foreground"
             
             Value="Red" />
    
             </Trigger>
    
            </Style.Triggers>
           </Style>
          </TreeView.ItemContainerStyle>
    
          <TreeView.Resources >
           <HierarchicalDataTemplate 
            DataType="{x:Type local:DomainViewModel}" 
            ItemsSource="{Binding Children}"
             >
            <StackPanel Orientation="Horizontal">
             <Image Width="20" Height="20" Margin="3,0" Source="Images\Computer.png" />
             <TextBlock Text="{Binding Name}" />
            </StackPanel>
           </HierarchicalDataTemplate>
    
           <HierarchicalDataTemplate 
            DataType="{x:Type local:TreeViewItemViewModel}" 
            ItemsSource="{Binding Children}"
            
            >
            <StackPanel Orientation="Horizontal">
             <Image Width="20" Height="20" Margin="3,0" Source="{Binding ImgPath}" />
             <TextBlock Text="{Binding Name}" />
            </StackPanel>
           </HierarchicalDataTemplate>
    
    
    
          </TreeView.Resources>
    
    
    
         </TreeView>
    

    and listview:

     <ListView Name="lv3" 
        FontSize="12" 
        BorderBrush="White" BorderThickness="0"
            
        ItemsSource="{Binding ElementName=nowtree, Path=SelectedItem.Children}"        
        ItemTemplateSelector="{StaticResource myDataTemplateSelector}" 
             
        >
          <ListView.ItemContainerStyle>
           <Style TargetType="{x:Type ListViewItem}">
    
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=twoway}" />
           </Style>
          </ListView.ItemContainerStyle>
    
          <ListView.ItemsPanel>
           <ItemsPanelTemplate>
            <UniformGrid >
            </UniformGrid>
           </ItemsPanelTemplate>       
          </ListView.ItemsPanel>
         </ListView>
    

    and my viewmodel:

    public class TreeViewItemViewModel : INotifyPropertyChanged
     {
      #region Data
      static readonly TreeViewItemViewModel DummyChild = new TreeViewItemViewModel();
      readonly ObservableCollection<TreeViewItemViewModel> _children;
      readonly TreeViewItemViewModel _parent;
      readonly DomainViewModel _pparent;  
      private string name;
      private string value;
      public string datatype;
      private string imgPath;
      object data;
      bool _isExpanded;
      bool _isSelected;
      private int machineid;
    .......................................
      #region IsExpanded
      /// <summary>
      /// Gets/sets whether the TreeViewItem 
      /// associated with this object is expanded.
      /// </summary>
      public bool IsExpanded
      {
       get { return _isExpanded; }
       set
       {
        if (!this.datatype.Equals("DeviceInstance") && !this.datatype.Equals("DeviceDetail"))
        {
         if (value != _isExpanded)
         {
          Console.WriteLine(this.name + "is expanded");
          _isExpanded = value;
          this.OnPropertyChanged("IsExpanded");
         }
    
         if (_isExpanded && _parent != null)
         {
          _parent.IsExpanded = true;
          Console.WriteLine("the parent:" + _parent.name + "is expanded by its child" + this.name);
         }
         if (_isExpanded && _pparent != null)
         {
          _pparent.IsExpanded = true;
          Console.WriteLine("the parent:" + _pparent.Name + "is expanded by its child" + this.name);
         }
         // Lazy load the child items, if necessary.
         if (this.HasDummyChild)
         {
         
           this.Children.Remove(DummyChild);
           this.LoadChildren(); 
         }
        }
       }
      }
    
      #endregion // IsExpanded
    
      #region IsSelected
    
      /// <summary>
      /// Gets/sets whether the TreeViewItem 
      /// associated with this object is selected.
      /// </summary>
      public bool IsSelected
      {
       get { return _isSelected; }
       set
       {    
        if(!this.datatype.Equals("DeviceDetail")){     
        if (value != _isSelected)
        {     
         _isSelected = value;
         this.OnPropertyChanged("IsSelected");
         if (_isSelected == true)
         {      
          Console.WriteLine(this.name + "isselected");
          if (this._pparent != null)
          {
           
           Console.WriteLine("Begin" + this.Name + "pparent" + this._pparent.IsSelected);
          }
          else
          {
           Console.WriteLine("Begin" + this.Name + "parent" + this._parent.IsSelected);
          }
          if (this.HasDummyChild)
          {
           if (_parent != null)
           {
            if (_parent.IsExpanded == false)
            {
             _parent.IsExpanded = true;
             Console.WriteLine(_parent.name + "is expanded by selecting its child:" + this.name);
            }
           }
           if (_pparent != null)
           {
            if (_pparent.IsExpanded == false)
            {
             _pparent.IsExpanded = true;
             Console.WriteLine(_pparent.Name + "is expanded by selecting its child:" + this.name);
            }
    
           }
    
            this.Children.Remove(DummyChild);
            this.LoadChildren();
    
          }
          else if (this.datatype.Equals("DeviceInstance"))
          {
    
           if (_parent.IsExpanded == false)
           {
            _parent.IsExpanded = true;
            Console.WriteLine(_parent.name + "is expanded by selecting its child:" + this.name);
           }
           this.LoadChildren();
    
          }
         }
         else
         {
          Console.WriteLine(this.name+"disselect");
         }
        }
        }
    
    
       }
      }
    
      #endregion // IsSelected
    }
    

    Now I can just click left treeview,and what the right listview show is correct.

    Also I can click right listview ,and left tree is also OK.

    But the problem is that If I have once expanded something in left, and click their parent node,then click any nodes in right listview ,there is a problem called InvalidOperationException.And it tells me that the collection has been changed,and cannot make enumerations.I have tried two days to solve this problem,and have no answers.I have checked every collection that I have used. After printing ,I find that the data is also loaded correct.I am also curious about that when I click something on the right,if the node I clicked is not expanded in left treeview(data has been loaded),the right listview will not change until I expand left treeview to the node I clicked.In myviewmodel,I can set parent node to expand ,so this condition is Ok,Is it the origin of this problem ,I don't know.

    2010年8月8日 12:05

全部回复