wpf treeview




WPF MVVM TreeView SelectedItem (4)

這不可能是這麼困難。 WPF中的TreeView不允許您設置SelectedItem,表示該屬性是ReadOnly。 我有TreeView填充,甚至在數據綁定集合更改時更新。

我只需要知道選擇了什麼項目。 我正在使用MVVM,因此沒有代碼隱藏或變量來引用樹視圖。 這是我找到的唯一解決方案 ,但它是一個明顯的黑客,它在XAML中創建了另一個元素,它使用ElementName綁定將自己設置為樹視圖選定項,然後您必須綁定Viewmodel。 關於此questions Several其他Several questions ,但沒有給出其他工作解決方案。

我已經看到了這個問題 ,但是使用給出的答案給了我編譯錯誤,由於某種原因我無法將混合sdk System.Windows.Interactivity的引用添加到我的項目中。 它說“未知的錯誤系統。窗口沒有被預加載”,我還沒有弄清楚如何通過它。

對於獎勵積分:為什麼微軟會讓這個元素的SelectedItem屬性ReadOnly?


使用OneWayToSource綁定模式。 這不起作用。 見編輯。

編輯 :根據這個問題 ,看起來這是微軟的一個錯誤或“按設計”行為; 但是,已經發布了一些解決方法。 為TreeView做任何工作嗎?

Microsoft Connect問題: https://connect.microsoft.com/WPF/feedback/details/523865/read-only-dependency-properties-does-not-support-onewaytosource-bindingshttps://connect.microsoft.com/WPF/feedback/details/523865/read-only-dependency-properties-does-not-support-onewaytosource-bindings

微軟於2010年1月10日下午2:46發布

我們今天無法在WPF中執行此操作,因為我們無法支持對不是DependencyProperties的屬性的綁定。 綁定的運行時每實例狀態保存在BindingExpression中,我們將其存儲在目標DependencyObject的EffectiveValueTable中。 當目標屬性不是DP或DP是只讀時,沒有地方存儲BindingExpression。

有一天我們可能會選擇將綁定功能擴展到這兩種情況。 我們經常被問到這些問題。 換句話說,您的請求已經在我們將來的版本中要考慮的功能列表中。

感謝您的反饋意見。


以MVVM可接受的方式解決此問題的一種非常不尋常但非常有效的方法如下:

  1. 在TreeView所在的View上創建一個可見性折疊的ContentControl。 適當地命名,並將其內容綁定到viewmodel中的某些SelectedSomething屬性。 這個ContentControl將“保持”所選對象並處理它的綁定,OneWayToSource;
  2. 在TreeView中監聽SelectedItemChanged ,並在代碼隱藏中添加一個處理程序,將ContentControl.Content設置為新選擇的項目。

XAML:

<ContentControl x:Name="SelectedItemHelper" Content="{Binding SelectedObject, Mode=OneWayToSource}" Visibility="Collapsed"/>
<TreeView ItemsSource="{Binding SomeCollection}"
    SelectedItemChanged="TreeView_SelectedItemChanged">

代碼背後:

    private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        SelectedItemHelper.Content = e.NewValue;
    }

視圖模型:

    public object SelectedObject  // Class is not actually "object"
    {
        get { return _selected_object; }
        set
        {
            _selected_object = value;
            RaisePropertyChanged(() => SelectedObject);
            Console.WriteLine(SelectedObject);
        }
    }
    object _selected_object;

您始終可以創建使用ICommand的DependencyProperty並在TreeView上偵聽SelectedItemChanged事件。 這可能比綁定IsSelected有點容易,但我想你無論如何都會因為其他原因而結束IsSelected。 如果您只想在IsSelected上綁定,則只要IsSelected發生更改,您就可以隨時發送消息。 然後,您可以在程序中的任何位置收聽這些消息。


我決定使用代碼隱藏和viewmodel代碼的組合。 xaml是這樣的:

<TreeView 
                    Name="tvCountries"
                ItemsSource="{Binding Path=Countries}"
                ItemTemplate="{StaticResource ResourceKey=countryTemplate}"   
                    SelectedValuePath="Name"
                    SelectedItemChanged="tvCountries_SelectedItemChanged">

代碼背後

private void tvCountries_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        var vm = this.FindResource("vm") as ViewModels.CoiEditorViewModel;
        if (vm != null)
        {
            var treeItem = sender as TreeView;
            vm.TreeItemSelected = treeItem.SelectedItem;
        }
    }

在viewmodel中有一個TreeItemSelected對象,您可以在viewmodel中訪問該對象。







treeview