2009-05-12 3 views
0

트릭을 성공적으로 적용한 경우 here이라고 설명했습니다. 하지만 여전히 문제가 하나 있습니다.여러 항목이있을 때 GroupStyle 합계가 업데이트되지 않음

요약 : 사용자를 ListView에 표시합니다. 사용자는 국가별로 재 그룹화되며, GroupStyle DataTemplate에서는 변환기를 사용하여 모든 그룹 관련 Users.Total의 합계를 표시합니다. 그러나 UI 사용자는 모달 창을 통해 사용자의 "총"속성 값을 변경할 수 있습니다.

그룹에 항목이 하나만있는 경우 표시된 총 사용자 수와 합계가 모두 올바르게 업데이트됩니다. 그러나 그룹에 여러 항목이있는 경우 User Total 만 (바인딩을 통해) 업데이트되지만 Sum (TotalSumConverter)을 호출해야하는 Converter도 호출되지 않습니다!

어디에서 왔는지 알고 있나요? 항목에 수정이있을 때 변환기가 호출되는지 확인하기 위해 트리거를 사용해야합니까?

답변

0

당신이 사용하는 속임수는 그룹 바닥 글을 ListView.Items에 자동 바인딩합니다. 예를 들어 DependencyObject가 자동으로보기를 업데이트하지 않습니다.

CollectionViewSource viewSource = FindResource("ViewSource") as CollectionViewSource; 
viewSource.View.Refresh(); 
0

보기를 새로 고침의 문제는 그것이 완전히 새로 고치는 것입니다, 그리고 난 원래 상태로 확장 할 것, 내 그룹에 대한 확장기를 대신 다음과 같이 총 각 업데이트 후 새로 고침을 강제로 사용자가 그들을 닫으면. 그렇습니다. 가능한 해결 방법이지만 완전히 만족스럽지 않습니다.

또한 DependencyObject 설명이 흥미 롭습니다. 그렇지만 내 그룹에 하나의 항목 만있을 때 왜 작동합니까?

3

문제는 변경된 항목에 대한 알림이 없기 때문에 항목이 변경 될 때 그룹의 모든 항목에 대한 합계를 계산하는 값 변환기가 실행되지 않는다는 것입니다. 한 가지 해결책은 알림을 수행하는 방법을 제어하고 필요한 경우 그룹 헤더에 알릴 수있는 다른 것으로 바인딩하는 것입니다.

다음은 작동 예제입니다. 텍스트 상자에서 사용자 수를 변경할 수 있으며 합계가 다시 계산됩니다.

XAML :

<Window x:Class="UserTotalTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:userTotalTest="clr-namespace:UserTotalTest" 
    Title="Window1" Height="300" Width="300" 
    Name="this"> 

    <Window.Resources> 

     <userTotalTest:SumConverter x:Key="SumConverter" /> 

     <CollectionViewSource Source="{Binding Path=Users}" x:Key="cvs"> 
      <CollectionViewSource.GroupDescriptions> 
       <PropertyGroupDescription PropertyName="Country"/> 
      </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 

    </Window.Resources> 

    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*" /> 
      <RowDefinition Height="10" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 
     <ListView 
      Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" 
      ItemsSource="{Binding Source={StaticResource cvs}}"> 
      <ListView.View> 
       <GridView> 
        <GridView.Columns> 
         <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name}" /> 
         <GridViewColumn Header="Count" DisplayMemberBinding="{Binding Path=Count}" /> 
        </GridView.Columns> 
       </GridView> 
      </ListView.View> 
      <ListView.GroupStyle> 
       <GroupStyle> 
        <GroupStyle.ContainerStyle> 
         <Style TargetType="{x:Type GroupItem}"> 
          <Setter Property="Template"> 
           <Setter.Value> 
            <ControlTemplate TargetType="{x:Type GroupItem}"> 
             <StackPanel Margin="10"> 
              <TextBlock Text="{Binding Path=Name}" FontWeight="Bold" /> 
              <ItemsPresenter /> 
              <TextBlock FontWeight="Bold"> 
               <TextBlock.Text> 
                <MultiBinding Converter="{StaticResource SumConverter}"> 
                 <MultiBinding.Bindings> 
                  <Binding Path="DataContext.Users" ElementName="this" /> 
                  <Binding Path="Name" /> 
                 </MultiBinding.Bindings> 
                </MultiBinding> 
               </TextBlock.Text> 
              </TextBlock> 
             </StackPanel> 
            </ControlTemplate> 
           </Setter.Value> 
          </Setter> 
         </Style> 
        </GroupStyle.ContainerStyle> 
       </GroupStyle> 
      </ListView.GroupStyle> 
     </ListView> 
     <ComboBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" 
      ItemsSource="{Binding Path=Users}" 
      DisplayMemberPath="Name" 
      SelectedItem="{Binding Path=SelectedUser}" /> 
     <TextBlock Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding Path=SelectedUser.Country}" /> 
     <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Path=SelectedUser.Count}" /> 
    </Grid> 
</Window> 

코드 숨김

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Globalization; 
using System.Linq; 
using System.Windows; 
using System.Windows.Data; 

namespace UserTotalTest 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      DataContext = new UsersVM(); 
     } 
    } 

    public class UsersVM : INotifyPropertyChanged 
    { 
     public UsersVM() 
     { 
      Users = new List<User>(); 
      Countries = new string[] { "Sweden", "Norway", "Denmark" }; 
      Random random = new Random(); 
      for (int i = 0; i < 25; i++) 
      { 
       Users.Add(new User(string.Format("User{0}", i), Countries[random.Next(3)], random.Next(1000))); 
      } 

      foreach (User user in Users) 
      { 
       user.PropertyChanged += OnUserPropertyChanged; 
      } 

      SelectedUser = Users.First(); 
     } 

     private void OnUserPropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 
      if (e.PropertyName == "Count") 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs("Users")); 
      } 
     } 

     public List<User> Users { get; private set; } 

     private User _selectedUser; 
     public User SelectedUser 
     { 
      get { return _selectedUser; } 
      set 
      { 
       _selectedUser = value; if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs("SelectedUser")); 
       } 
      } 
     } 

     public string[] Countries { get; private set; } 

     #region INotifyPropertyChanged Members 
     public event PropertyChangedEventHandler PropertyChanged; 
     #endregion 
    } 

    public class User : INotifyPropertyChanged 
    { 
     public User(string name, string country, double total) 
     { 
      Name = name; 
      Country = country; 
      Count = total; 
     } 

     public string Name { get; private set; } 
     private string _country; 
     public string Country 
     { 
      get { return _country; } 
      set 
      { 
       _country = value; 
       if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs("Country")); 
       } 
      } 
     } 

     private double _count; 
     public double Count 
     { 
      get { return _count; } 
      set 
      { 
       _count = value; if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs("Count")); 
       } 
      } 
     } 

     #region INotifyPropertyChanged Members 
     public event PropertyChangedEventHandler PropertyChanged; 
     #endregion 
    } 

    public class SumConverter : IMultiValueConverter 
    { 
     public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
     { 
      IEnumerable<User> users = values[0] as IEnumerable<User>; 
      string country = values[1] as string; 
      double sum = users.Cast<User>().Where(u =>u.Country == country).Sum(u => u.Count); 
      return "Count: " + sum; 
     } 

     public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 
관련 문제