2010-03-12 26 views
5

[Original]
Tôi có một ListBox trong đó có nó ItemsSource (điều này được thực hiện trong các mã sau vào như cửa sổ được tạo ra) databound đến một ObservableCollection. Các ListBox sau đó có DataTemplate sau giao chống lại các mục:DataTrigger không đánh giá lại tài sản sau khi thay đổi

usercontrol.xaml

<ListBox x:Name="communicatorListPhoneControls" 
     ItemContainerStyle="{StaticResource templateForCalls}"/> 

App.xaml

<Style x:Key="templateForCalls" TargetType="{x:Type ListBoxItem}"> 
    <Setter Property="ContentTemplate" Value="{StaticResource templateRinging}"/> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Path=hasBeenAnswered}" Value="True"> 
       <Setter Property="ContentTemplate" Value="{StaticResource templateAnswered}"/> 
      </DataTrigger> 
     </Style.Triggers> 
    </Setter> 
</Style> 

Khi ObservableCollection được cập nhật với một đối tượng, điều này xuất hiện trong ListBox với chính xác ban đầu DataTemplate, tuy nhiên khi thuộc tính hasBeenAnswered được đặt thành true (khi gỡ lỗi tôi có thể thấy bộ sưu tập chính xác) DataTrigger không đánh giá lại và sau đó cập nhật ListBox để sử dụng đúng DataTemplate.

Tôi đã triển khai sự kiện INotifyPropertyChanged Sự kiện trong đối tượng của mình và nếu trong mẫu bị ràng buộc với giá trị, tôi có thể thấy cập nhật giá trị. Chỉ là DataTrigger sẽ không đánh giá lại và thay đổi thành mẫu chính xác.

Tôi biết ràng buộc DataTrigger là chính xác vì nếu tôi đóng cửa sổ và mở lại, nó sẽ áp dụng chính xác bảng dữ liệu thứ hai, vì hasBeenAnswered được đặt thành true.

[sửa 1]
Sau ngày từ bình tạo bởi Timores Tôi đã thử như sau:

usercontrol.xaml

<ListBox x:Name="communicatorListPhoneControls" 
     ItemTemplate="{StaticResource communicatorCallTemplate}"/>` 

App.xaml:

<DataTemplate x:Key="communicatorCallTemplate"> 
    <Label x:Name="test">Not answered</Label> 
     <DataTemplate.Triggers> 
      <DataTrigger Binding="{Binding Path=hasBeenAnswered}" Value="True"> 
       <Setter TargetName="test" Property="Background" Value="Blue"/> 
      </DataTrigger>  
     </DataTemplate.Triggers> 
    </Label> 
</DataTemplate> 

Điều gì xảy ra bây giờ tương tự như ví dụ đầu tiên, khi có cuộc gọi đến trong chương trình nhãn "Không được trả lời" (mỗi cuộc gọi tồn tại vì đây là hộp danh sách - thông thường khi cửa sổ tải sẽ không có cuộc gọi), cuộc gọi sau đó được trả lời và số hasBeenAnswered được đặt thành true, nhưng "Không được trả lời" vẫn giữ nguyên. Nếu tôi đóng cửa sổ và mở lại nó (với cuộc gọi hiện tại vẫn còn với thuộc tính hasBeenAnswered được đặt thành true) thì nền sau đó sẽ màu xanh dương. Vì vậy, nó sẽ xuất hiện với tôi như datatrigger chỉ đơn giản là không được chạy, cho đến khi cửa sổ được chạy lại.

Trả lời

1

Điều gì có vẻ lạ đối với tôi trong ví dụ này là bạn đang sử dụng một ItemContainerStyle thay vì một ItemTemplate.

ItemContainerStyle áp dụng cho ListBoxItem chứa mỗi phần tử trong ItemsSource của bạn. ListboxItem không có thuộc tính hasBeenAnswered, vì vậy tôi không thấy cách liên kết có thể hoạt động.

Tôi khuyên bạn nên tạo DataTemplate cho loại dữ liệu trong hộp danh sách của bạn và sử dụng trình kích hoạt để thực hiện các thay đổi tương tự như trong kiểu templateAnswered của bạn.

Chỉnh sửa: sau khi OP đã sử dụng đề xuất của ItemTemplate.

Tôi đã cố tạo lại ví dụ và nó hoạt động tốt cho tôi. Đây là XAML của tôi (xin vui lòng bỏ qua phong cách, đây chỉ là một ví dụ):

Không trả lời

<ListBox x:Name="communicatorListPhoneControls" 
      ItemTemplate="{StaticResource communicatorCallTemplate}"/> 

    <Button Margin="0,20,0,0" Click="OnToggleAnswer" Content="Toggle answer status" /> 
</StackPanel> 

Và trong số- đằng sau:

public partial class Window1 : Window { 

    public Window1() { 
     InitializeComponent(); 

     List<PhoneCall> lpc = new List<PhoneCall>() 
     {new PhoneCall(), new PhoneCall(), new PhoneCall(), new PhoneCall()}; 

     communicatorListPhoneControls.ItemsSource = lpc; 
    } 

    private void OnToggleAnswer(object sender, RoutedEventArgs e) { 

     object o = communicatorListPhoneControls.SelectedItem; 

     if (o != null) { 

      PhoneCall pc = (PhoneCall) o; 
      pc.hasBeenAnswered = ! pc.hasBeenAnswered; 
     } 
    } 
} 

public class PhoneCall : INotifyPropertyChanged { 

    private bool _answered; 


    public bool hasBeenAnswered { 
     get { return _answered; } 
     set { 
      if (_answered != value) { 
       _answered = value; 
       FirePropertyChanged("hasBeenAnswered"); 
      } 
     } 
    } 

    private void FirePropertyChanged(string propName) { 

     if (PropertyChanged != null) { 

      PropertyChanged(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

Bạn có thể thử tạo lại mã này và so sánh với mã của mình không? Lưu ý: lỗi nhỏ nhất trong tên thuộc tính được gán cho PropertyChanged có thể giải thích hành vi của bạn. Trình kích hoạt có thể dựa trên thuộc tính đúng, nhưng thông báo có thể có một tên sai chính tả.

+0

Tôi đã thử triển khai điều này nhưng nó vẫn chỉ áp dụng nếu tôi đóng cửa sổ và mở lại lần nữa. Tôi sẽ thêm vào bình luận trong đầu để thể hiện điều này. Bạn có bất cứ ý tưởng? –

+0

AHHHHH! Tôi đã có nó, chính tả ngu ngốc của riêng tôi, bạn đã chính xác, trong INotifyProperyChanged tôi đã "hasBeenAsnwered" thay vì "hasBeenAnswered". riêng Boolean _hasBeenAnswered; công khai Boolean hasBeenAnswered { nhận {return _hasBeenAnswered; } đặt { _hasBeenAnswered = value; NotifyPropertyChanged ("hasBeenAnswered"); } } } cảm ơn sự giúp đỡ của bạn. –

+0

Bạn được chào đón. Nhưng tôi đã sai ban đầu, tức là DataContext trong ItemContainerStyle thực sự là mục bên trong, không phải là ListBoxItem. Tôi đã thay đổi ví dụ của tôi để giống như câu hỏi ban đầu của bạn, và nó cũng hoạt động. – Timores

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