2016-08-15 77 views
1

我遇到了一個問題,我在診斷時遇到了一些麻煩。爲什麼我的依賴屬性將null發送給我的視圖模型?

我已經創建了一個自定義的DataGrid對象(詳見Sandesh的回答here),以便能夠綁定到數據網格的各種選定項目。然而,即使它看起來像DependecyProperty本身在選擇更改時獲得正確的值,視圖模型似乎永遠不會接收更新的值(它會變爲null)。

自定義DataGrid類:

class CustomDataGrid : DataGrid 
{ 
    public CustomDataGrid() 
    { 
     this.SelectionChanged += CustomDataGrid_SelectionChanged; 
    } 

    void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     this.SelectedItemsList = this.SelectedItems; 
    } 
    #region SelectedItemsList 

    // In the setter, the value is a valid List with the correct elements. 
    // For some reason it doesn't seem to be passed on to the view model. 
    public IList SelectedItemsList 
    { 
     get { return (IList)GetValue(SelectedItemsListProperty); } 
     set { SetValue(SelectedItemsListProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedItemsListProperty = 
      DependencyProperty.Register("SelectedItemsList", typeof(IList), typeof(CustomDataGrid), new PropertyMetadata(OnSelectedItemsListChanged)); 

    private static void OnSelectedItemsListChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine("Test"); 
    } 

    #endregion 
} 

XAML文件:

<Window x:Class="Test.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:Test" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:TestViewModel /> 
    </Window.DataContext> 
    <Grid> 
     <local:CustomDataGrid AutoGenerateColumns="True" 
           SelectionMode="Extended" 
           SelectionUnit="FullRow" 
           CanUserAddRows="False" 
           CanUserDeleteRows="False" 
           CanUserResizeRows="False" 
           ItemsSource="{Binding TestModels}" 
           SelectedItemsList="{Binding Path=SelectedTestModels, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />  
    </Grid> 
</Window> 

視圖模型:

class TestViewModel : INotifyPropertyChanged 
{ 
    public TestViewModel() 
    { 
     TestModels = new List<TestModel> 
     { 
      new TestModel { Name = "Test 1", ID = 1 }, 
      new TestModel { Name = "Test 2", ID = 2 }, 
      new TestModel { Name = "Test 3", ID = 3 }, 
     }; 
    } 

    private IEnumerable<TestModel> _testModels; 

    public IEnumerable<TestModel> TestModels 
    { 
     get { return _testModels; } 
     set 
     { 
      _testModels = value; 
      OnPropertyChanged(); 
     } 
    } 

    private IEnumerable<TestModel> _selectedTestModels; 

    public IEnumerable<TestModel> SelectedTestModels 
    { 
     get { return _selectedTestModels; } 
     set 
     { 
      // Right here I would expect value to have a non-null value... but it's always null 
      _selectedTestModels = value; 
      OnPropertyChanged(); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var propChanged = PropertyChanged; 
     if (propChanged != null) 
      propChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

的TestModel類(非常簡單的POCO):

class TestModel 
{ 
    public string Name { get; set; } 
    public int ID { get; set; } 
} 
+0

在Visual Studio的輸出窗口中是否存在任何綁定錯誤消息? 'IList'可能不能從'IEnumerable '分配。 – Clemens

+0

沒有出現在輸出窗口中的錯誤消息,綁定或其他。此外,如果我將視圖模型中'TestModels'和'SelectedTestModels'的類型更改爲'IList ',我仍會得到一個空值。 –

回答

1

您可以交替使用非通用IList和IList。你有幾個選擇。

在您的viewmodel中,您可以將您的屬性和字段更改爲IList。

private IList _selectedTestModels; 

public IList SelectedTestModels 
{ 
    get { return _selectedTestModels; } 
    set 
    { 
     _selectedTestModels = value; 
     OnPropertyChanged(); 
    } 
} 

或者在您的CustomControl中。

public static readonly DependencyProperty SelectedItemsListProperty = DependencyProperty.Register("SelectedItemsList", typeof(IList<TestModel>), typeof(CustomDataGrid)); 

public IList<TestModel> SelectedItemsList 
{ 
    get { return (IList<TestModel>)GetValue(SelectedItemsListProperty); } 
    set { SetValue(SelectedItemsListProperty, value); } 
} 

void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    SetCurrentValue(SelectedItemsListProperty, SelectedItems.OfType<TestModel>().ToList()); 
} 

作爲一個方面說明,我也相信這一點的代碼可能會打破你的約束力。

void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    this.SelectedItemsList = this.SelectedItems; 
} 

嘗試使用SetCurrentValue來維持您的綁定。

void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    SetCurrentValue(SelectedItemsListProperty, SelectedItems); 
} 
+0

對不起,它看起來並沒有做任何事情。視圖模型仍然接收null。 –

+0

我不認爲這是你的綁定,我認爲你的IList在CustomControl中爲null。嘗試在你的SelectionChanged事件結束時放置一個斷點和下面的代碼,我打賭SelectedItemsList也是空的。 var test = SelectedItemsList; –

+0

你是對的。如果在執行'this.SelectedItemsList = this.SelectedItems'調用之後添加該行,'SelectedItemsList'仍然爲null,即使'SelectedItems'有效且包含數據。我將如何去解決這個問題? –

相關問題