2011-07-04 3 views
1

TextBlock의 Text를 "Name (null이 아닌 속성의 항목 수)"과 같이 설정해야합니다. 지금은 ItemsSource.Count를 사용하여 전체 컬렉션의 항목 수를 사용하여이 작업을 수행합니다. 이를 위해 ObservableCollection의 부분에 대한 WPF 멀티 바인딩

<TextBlock x:Name="textBlockHeader" > 
    <TextBlock.Text> 
     <MultiBinding Converter="{StaticResource headerCreator}" x:Name="multiBinder"> 
      <Binding ElementName="trackingTable" Path="Name" /> 
      <Binding ElementName="trackingsGrid" Path="ItemsSource.Count" /> 
     </MultiBinding> 
    </TextBlock.Text> 
</TextBlock> 

는 I는 IMultiValueConverter가 사용하고

internal class HeaderCreator : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     // Based on this xaml 
     ////<Binding ElementName="trackingTable" Path="Name" />     values[0] 
     ////<Binding ElementName="trackingsGrid" Path="ItemsSource.Count" /> values[1] 

     return values[0] + " (" + values[1] + ")"; 
    } 

trackingsGrid가 TrackingData 오브젝트를 갖는 컬렉션에 바인더 제본 (여기서 코드를 도시하지 않음) 아래에 정의 된 데이터 그리드이다. TrackingData에는 Tracking이라는 속성이 있습니다. 이 속성이 null 인 ObservableCollection의 항목 만 계산해야합니다. 이것을 어떻게 할 수 있습니까?

public class TrackingData : INotifyPropertyChanged 
{ 
    public Model.ITracking Tracking { get; set; } 
    ... 
} 

미리 감사드립니다.

답변

2

이 논리 (이 속성이 null이 아닌 ObservableCollection의 항목)를 ViewModel에두고이 속성에 바인딩합니다.

+0

Logic을 ViewModel의 ItemsCount 속성으로 이동했습니다. 그 Setter에서 OnPropertyChanged가 해고되었습니다. ItemsCount는 ICollectionView.CollectionChanged에 대한 대리자로 설정됩니다. 모든 답변이 도움이되었습니다. 고마워요! – GRF

0

전적으로 필요하지 않는 한 MultiBinding을 사용하지 않는 것이 좋습니다. 필요시 줄을 그리기는 어렵지만 일반적으로 원하는 동작을 달성 할 수있는 다른 옵션이 없을 때 또는 대안 구현에 상당한 노력이 필요할 때를 알 수 있습니다. 내 직감은 성능면에서 효율성이 낮을뿐만 아니라 읽기, 테스트 및 유지 관리가 더 어려워서 MultiBinding라고 알려줍니다.

ViewModel의 속성 (@polishchuk가 제시하는대로)을 사용하거나 뷰 모델을 기반으로 형식이 지정된 문자열을 반환하는 전체보기 모델 및 단일 변환기에 바인딩하여 원하는 동작을 얻을 수 있다고합니다. 두 가지 옵션 중에서 고급 텍스트 서식이 필요하지 않다면 첫 번째 옵션을 선호하고 그렇지 않으면 두 번째 옵션을 선호합니다.

1

개인적으로 매우 맞춤 설정 되었기 때문에 개인적으로 ViewModel에 추가 할 것입니다.

즉, 몇 가지 사소한 조작으로이 작업을 수행 할 수 있습니다. 먼저 두 번째 바인딩을 ItemsSource.Count에서 ItemsSource으로 변경합니다. 이로 인해 IMultiValueConvertervalues[1]이 전체 컬렉션이됩니다. 이 작업을 완료하면

, 당신의 컨버터는 변경 될 수 있습니다, 그래서 당신은보고 :

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
{ 
    // Based on this xaml 
    ////<Binding ElementName="trackingTable" Path="Name" />     values[0] 
    ////<Binding ElementName="trackingsGrid" Path="ItemsSource" /> values[1] 
    IEnumerable<TrackingData> tracking = values[1] as IEnumerable<TrackingData>; 
    if(tracking == null) 
     return values[0] + " (0)"; // Put some reasonable value here? 

    return values[0] + " (" + tracking.Where(t => t.Tracking != null).Count() + ")"; 
} 
+0

나는 당신의 빠른 해결책을 시도했다. 나는 이것이 하나라고 생각했다. TextBlock이 시작되지만 확인은 업데이트되지 않습니다. – GRF

+0

@GRF : 여기 MultiValueCOnverter를 사용하는 문제 중 일부입니다. 개별 요소 변경 사항을 절대 업데이트하지 않습니다. 사실, 모든 요소가 변경된 모든 소품을보아야하기 때문에 실제로는 매우 어렵습니다. –

+0

@GRF : 저는이 상황을 처리하는 방법에 대한 전체 예제를 실제로 작성했습니다 : http://reedcopsey.com/2009/10/14/using-a-behavior-to-aggregate-values-in-a-master -detail-view-in-mv-vm / –

0

명 몇 내가 뷰 모델에이 논리를 움직일 것입니다 지적한다. 여기에 하나의 쉬운 방법이있어서 많은 이벤트 핸들러를 연결하고 커스텀 로직을 작성할 필요가 없습니다 :

ViewModel에서 이것을 구현하는 쉬운 방법 중 하나는 ICollectionView을 생성하여 소스 컬렉션을 랩핑하고 그것에 필터는 누구의 재산 null가 아닌

IList<T> source = ... 
ListCollectionView customView = new ListCollectionView(source); 
customView.Filter = obj => ((TrackingData)obj).Tracking != null; 

그럼 당신은 proprerty로 뷰 모델을 통해이 ICollectionView에 노출 될 수 있습니다 만 값을 포함

TrackedItems 그런 다음 XAML에서 당신이 TrackedItems.Count에 데이터 바인딩 수 있다고합니다. ICollectionView은 TrackingData 개체 속성이 변경 될 때 동기화 상태를 유지합니다.

관련 문제