2015-12-30 34 views
2

我有簡單的ListView觸發器,我也使用mvvm light RelayCommand。 主要問題是爲什麼當功能ChangeShowingMode(ObservableCollection<Employee> items)在控制檯中觸發時,它只顯示Firing: 0。爲什麼它不顯示Firing: 1,Firing: 5,Firing: 11,Firing: 99。如何做到這一點?ListView與混合觸發器的奇怪行爲

的xmlns:ⅰ= 「http://schemas.microsoft.com/expression/2010/interactions」 的xmlns:EI = 「http://schemas.microsoft.com/expression/2010/interactivity」

<Grid> 
    <ListView ItemsSource="{Binding Items}"> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition/> 
         <ColumnDefinition/> 
        </Grid.ColumnDefinitions> 
        <CheckBox IsChecked="{Binding IsChecked}" VerticalAlignment="Center"> 
         <ei:Interaction.Triggers> 
          <ei:EventTrigger EventName="Checked"> 
           <ei:InvokeCommandAction Command="{Binding DataContext.IsCheckedTrueCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Views:MainWindow}}}" CommandParameter="{Binding .}"/> 
          </ei:EventTrigger> 
         </ei:Interaction.Triggers> 
        </CheckBox> 
        <Label Grid.Column="1" Content="{Binding Name}" VerticalAlignment="Center"/> 
       </Grid> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
</Grid> 

代碼如下所示:

namespace WpfApplication 
{ 
/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new ListViewModel(); 
    } 
} 
public class Employee : ViewModelBase 
{ 
    private bool isChecked; 
    public bool IsChecked 
    { 
     get 
     { 
      return this.isChecked; 
     } 

     set 
     { 
      this.isChecked = value; 
      this.RaisePropertyChanged("IsChecked"); 
     } 
    } 

    public string Name { get; set; } 
} 
public class ListViewModel : ViewModelBase 
{ 
    private ObservableCollection<Employee> items; 
    public ObservableCollection<Employee> Items 
    { 
     get 
     { 
      return this.items; 
     } 

     set 
     { 
      this.items = value; 
      this.RaisePropertyChanged("Items"); 
     } 
    } 

    public ListViewModel() 
    { 
     Items = new ObservableCollection<Employee>(); 
     LoadAsync(); 
    } 
    public void LoadAsync() 
    { 
     Task t = null; 
     t = Task.Factory.StartNew(new Action(() => 
     { 
      System.Threading.Thread.Sleep(5000); 
      ObservableCollection<Employee> temporaryItems = new ObservableCollection<Employee>(); 
      for (int i = 0; i < 100; i++) 
      { 
       temporaryItems.Add(new Employee { IsChecked = false, Name = i.ToString() }); 
      } 
      Items = temporaryItems; 
     })); 
     t.ContinueWith((key) => { ChangeShowingMode(Items); }); 
    } 
    public void ChangeShowingMode(ObservableCollection<Employee> items) 
    { 
     Items[0].IsChecked = true; 
     Items[1].IsChecked = true; 
     Items[5].IsChecked = true; 
     Items[11].IsChecked = true; 
     Items[99].IsChecked = true; 
    } 

    public RelayCommand<Employee> IsCheckedTrueCommand 
    { 
     get 
     { 
      return new RelayCommand<Employee>((emp) => Command(emp)); 
     } 
    } 

    public void Command(Employee emp) 
    { 
     Console.WriteLine("Firing: {0}", emp.Name); 
    } 
} 

}

+0

假設'IsChecked'引發'INPC.PropertyChanged'事件我猜這是做些什麼你做你它從'任務'。你可以通過調用'PropertyChanged'事件來改變任何''的Employee.IsChecked'屬性 – dkozl

+0

你錯了,因爲t.ContinueWith((key)=> {ChangeShowingMode(Items);} ); 在UI線程中引發。我認爲問題在於虛擬化或其他類似的問題。 – A191919

+0

不,它不。直到你指定了適當的'TaskScheduler',例如'TaskScheduler.FromCurrentSynchronizationContext()' – dkozl

回答

1

選中的事件將RAI僅適用於可見的複選框。所以這個命令只能用於可見的命令。

sample UI

通過測試您提供的示例中,屬性是由任務設置,也體現爲預期的UI。但是隻有當我手動檢查複選框時纔會調用命令,而不是通過初始化。

更改

t.ContinueWith((key) => { ChangeShowingMode(Items); }); 

t.ContinueWith((key) => { Syste.Threading.Thread.Sleep(5000); ChangeShowingMode(Items); }); 

具有這樣的結果,該命令要求可見覆選框。 如果您在顯示覆選框時進行滑動,則會爲複選框99調用該命令。

但是,這種行爲根本不奇怪。我認爲,這是一個很好的問題 - 當你的視圖模型連接到Datacontext或沒有。

您的問題的答案「如何做到這一點?」取決於你目前的解決方案有什麼問題。

要觀看房產更改,您可以登錄 How to Listen to Property Changes of Items of an ObservableCollection 並調用有關更改的命令。

但我認爲你根本不需要這個。檢查狀態通過雙向綁定反映在您的IsChecked-Property中。

<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center"> 

所以,你可以很容易地通過

var checkedItemsList = Items.Where(ele => ele.IsChecked).ToList(); 

讓他們如果你通過代碼進行更改,您可以在您的視圖模型手動調用命令。

Items[0].IsChecked = true; 
if (IsCheckedTrueCommand.CanExecute(Items[0])) 
    IsCheckedTrueCommand.Execute(Items[0]); 

但我不知道我是否能把你帶到這裏。問題仍然是命令應該在增強的場景中做什麼。

順便說一句,你正在使用哪個版本的框架?見check box binding not working on .NET 3.5 SP1

,並呼籲對用戶交互的COMAND你可以使用:

<CheckBox CommandParameter="{Binding}" 
           Command="{Binding DataContext.CheckBoxCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 
           IsChecked="{Binding IsChecked, Mode=TwoWay}" VerticalAlignment="Center"> 
+0

在我的代碼中替換t.ContinueWith((key)=> {ChangeShowingMode(Items);}); ((key)=> {Syste.Threading.Thread.Sleep(5000); ChangeShowingMode(Items);});我想這也會讓你感到驚訝:) – A191919

+0

@ A191919我檢查了這個,看到我更新的答案。新年快樂! – gReX