5

Tôi có một ObservableCollection ràng buộc vào một hộp danh sách boolean sở hữu ràng buộc vào một nút . Sau đó tôi đã xác định hai bộ chuyển đổi, bộ chuyển đổi hoạt động trên bộ sưu tập và bộ kia hoạt động trên thuộc tính boolean. Bất cứ khi nào tôi sửa đổi thuộc tính boolean, phương thức Chuyển đổi của trình biến đổi được gọi, trong đó giống như không được gọi nếu tôi sửa đổi tập hợp quan sát được. Tôi đang thiếu gì ??Khi phương pháp Chuyển đổi của ValueConverter sẽ được gọi trong WPF

Snippets để bạn tham khảo,

XAML snipet,

<Window.Resources> 
    <local:WrapPanelWidthConverter x:Key="WrapPanelWidthConverter" /> 
    <local:StateToColorConverter x:Key="StateToColorConverter" /> 
</Window.Resources> 
<StackPanel> 
    <ListBox x:Name="NamesListBox" ItemsSource="{Binding Path=Names}"> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel x:Name="ItemWrapPanel" Width="500" Background="Gray"> 
        <WrapPanel.RenderTransform> 
         <TranslateTransform x:Name="WrapPanelTranslatation" X="0" /> 
        </WrapPanel.RenderTransform> 
        <WrapPanel.Triggers> 
         <EventTrigger RoutedEvent="WrapPanel.Loaded"> 
          <BeginStoryboard> 
           <Storyboard> 
            <DoubleAnimation Storyboard.TargetName="WrapPanelTranslatation" Storyboard.TargetProperty="X" To="{Binding Path=Names,Converter={StaticResource WrapPanelWidthConverter}}" From="525" Duration="0:0:2" RepeatBehavior="100" /> 
           </Storyboard> 
          </BeginStoryboard> 
         </EventTrigger> 
        </WrapPanel.Triggers> 
       </WrapPanel> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Label Content="{Binding}" Width="50" Background="LightGray" /> 
       </Grid> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <Button Content="{Binding Path=State}" Background="{Binding Path=State, Converter={StaticResource StateToColorConverter}}" Width="100" Height="100" Click="Button_Click" /> 
</StackPanel> 

mã sau đoạn mã

public class WrapPanelWidthConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     ObservableCollection<string> aNames = value as ObservableCollection<string>; 
     return -(aNames.Count * 50); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 


public class StateToColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     bool aState = (bool)value; 
     if (aState) 
      return Brushes.Green; 
     else 
      return Brushes.Red; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Trả lời

11

Tôi nghĩ rằng bộ chuyển đổi trong một Binding luôn gọi nếu nguồn Binding đã được cập nhật và thông báo về bản cập nhật đó (dưới dạng DependencyProperty hoặc sử dụng INotifyPropertyChanged). Tuy nhiên, một ObservableCollection không tăng sự kiện PropertyChanged nếu một mục đã được thêm hoặc xóa, nhưng nó làm tăng sự kiện CollectionChanged. Nó không tăng bất kỳ sự kiện nào nếu một mục trong bộ sưu tập được thay đổi. Ngay cả khi bản thân mục đó tăng lên PropertyChanged, mục này sẽ không cập nhật số Binding trên bộ sưu tập vì nguồn Binding không phải là mục mà là bộ sưu tập.

Tôi lo sợ cách tiếp cận của bạn sẽ không hoạt động theo cách này. Bạn có thể liên kết trực tiếp với ObservableCollection.Count và thêm trình chuyển đổi toán thích hợp vào nó để thực hiện đảo ngược và phép nhân, nhưng thuộc tính Count không thực hiện thay đổi thông báo, vì vậy tùy chọn này không có. Tôi nghĩ bạn sẽ phải cung cấp một tài sản khác trong ViewModel của bạn hoặc mã phía sau xử lý các trường hợp này ...

+0

Bất cứ khi nào một mục được bổ sung vào bộ sưu tập, các thành viên ObservableCollection là nâng CollectionModified biến cố. Trong trường hợp Trình chuyển đổi chỉ được kích hoạt khi Thuộc tính được sửa đổi. Để giải quyết sự cố này, người dùng có thể đăng ký sự kiện đã sửa đổi bộ sưu tập và sau đó tăng sự kiện PropertyChanged bằng tên thuộc tính của ObservableCollection. – sudarsanyes

+0

Vừa mới xem qua câu trả lời của bạn và tôi cũng phỏng đoán như vậy. – sudarsanyes

+0

Cách giải quyết của bạn có thể hoạt động, nhưng bạn nên lưu ý rằng cách giải quyết này sẽ cập nhật ràng buộc hoàn chỉnh, tức là bộ sưu tập được đọc lại và tất cả các mục trong bộ sưu tập của bạn được tạo lại một lần nữa. Ít nhất, đó là những gì tôi mong đợi. Tôi muốn khuyên bạn nên ràng buộc với một thuộc tính 'Count' tùy chỉnh, nhưng nó phụ thuộc vào kịch bản của bạn cho dù đó là giá trị trên đầu. – gehho

2

Trình biến đổi được gọi khi liên kết xảy ra hoặc thay đổi thuộc tính. Vì vậy, công cụ chuyển đổi của bạn được gọi cho boolean của bạn bất cứ khi nào giá trị của các thay đổi boolean. Bộ sưu tập của bạn được đặt một lần và đó là khi sự ràng buộc xảy ra và bộ chuyển đổi được sử dụng. Khi nội bộ của bộ sưu tập thay đổi (bộ sưu tập được thêm vào hoặc bị xóa khỏi) thuộc tính không thay đổi (tức là bạn không ràng buộc bộ sưu tập mới) để bộ chuyển đổi của bạn không kích hoạt lại.

Sử dụng mô hình chế độ xem và bọc bộ sưu tập của bạn và thêm một thuộc tính khác như số đếm thực hiện thay đổi thông báo. Bạn có thể sử dụng lớp trình bao bọc này từ here sẽ bao bọc bộ sưu tập của bạn và sẽ dễ dàng thêm thuộc tính ở đó.

11

Bộ chuyển đổi đa khe có thể được sử dụng để khắc phục vấn đề này. Sau đó, bạn có thể liên kết với thuộc tính Collection.Count và bộ sưu tập cùng một lúc. Số đếm sẽ kích hoạt các ràng buộc để có được tái đánh giá và sau đó bạn sử dụng các ràng buộc thứ hai để thực sự chuyển đổi các giá trị theo yêu cầu

      <TextBlock IsHitTestVisible="false" 
           Margin="5,0" 
           TextTrimming="CharacterEllipsis" 
           VerticalAlignment="Center" 
           DockPanel.Dock="Left" > 
           <TextBlock.Text> 
            <MultiBinding Converter="{Resources:ListToStringConverter}"> 
             <Binding Path="List.Count" /> 
             <Binding Path="List" /> 
            </MultiBinding> 
           </TextBlock.Text> 
          </TextBlock> 
+0

Cảm ơn bạn vì ý tưởng này! Trong khi các câu trả lời ở trên đã không làm việc ở tất cả cho tôi, điều này không. Tôi cần phải sửa đổi công cụ chuyển đổi của mình một chút để triển khai IMultiValueConverter thay vì IValueConverter, và tôi cần phải làm rõ chỉ mục bộ sưu tập của tôi sẽ là gì, nhưng sau đó tất cả đều ổn. – ygoe

+0

Rực rỡ! Ý tưởng đó đã giúp tôi tiết kiệm rất nhiều thời gian. – gbc

+0

Tuyệt vời, cảm ơn bạn! – Aybe

Các vấn đề liên quan