WPF開發為按鈕提供添加,刪除和重新排列ListBox內容的功能


介紹

我有一種情況,我希望能夠將項目添加到列表中,並在列表中移動項目,這似乎是使用a的最簡單方法ListBox我立刻想到了如何以通用的方式做到這一點,然后,也許,可以使用行為來做到這一點。這似乎是一個非常有用的想法。我決定以一種簡單的方式為我正在開發的應用程序做這件事,但我想我會創建一個演示項目來探索這個想法。這是結果。

概觀

該行為實際上有四個獨立的部分,可以在一個類中執行不同的功能:

  • 添加項目
  • 將所選項目向上移動一個位置
  • 將所選項目向下移動一個位置
  • 刪除所選項目。

每個函數的代碼結構非常相似,只有一些細節不同。

將要檢查的代碼是Move Up函數的代碼

首先是以下定義DependencyProperty

public static readonly DependencyProperty MoveItemUpProperty = DependencyProperty.RegisterAttached("MoveItemUp", typeof(Selector), typeof(ListHelperBehavior), new PropertyMetadata(null, OnMoveItemUpChanged)); public static Selector GetMoveItemUp(UIElement uiElement) { return (Selector)uiElement.GetValue(MoveItemUpProperty); } public static void SetMoveItemUp(UIElement uiElement, Selector value) { uiElement.SetValue(MoveItemUpProperty, value); } 

這用於為包含列表Selector(或ListBox)控件提供綁定它用於Button執行動作,在這種情況下是將所選項目向上移動一個位置。對於這個動作的代碼需要有機會獲得ItemsSourceSelectedIndexSelector控制,首先要真正能夠做到移動,第二知道要移動的項目。

對於所有操作,此代碼幾乎相同,只是Add Item不需要監視SelectionChanged事件Selector,並且Button永遠不會禁用。

當此DependencyProperty更改時,將OnMoveUpItemChanged執行事件處理程序此事件處理程序在DependencyPropertyRegisterAttached方法的FrameworkMetadata參數中指定

private static void OnMoveItemUpChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.OldValue is Selector Selector1) { Selector1.SelectionChanged -= SetMoveItemUpButtonIsEnabled; } if (e.NewValue is Selector Selector) { var Button = CheckForButtonBase(d); Button.Click -= MoveItemUpEvent; Button.Click += MoveItemUpEvent; Selector.SetValue(MoveUpButton, Button); Selector.SelectionChanged += SetMoveItemUpButtonIsEnabled; SetMoveItemUpButtonIsEnabled(Selector, null); } } 

此代碼將事件處理程序附加到ButtonClick事件和Selector SelectionChanged事件。為了確保Button在訂閱事件之前沒有雙重訂閱Click事件,並且刪除SelectionChanged事件的事件處理程序Selector(如果存在)。此外,Button它保存在附件DependencyProperty中,Selector以便可以找到它以供SelectionChanged事件處理程序使用最后,Button通過使用SelectionChanged事件處理程序調整IsEnabled值

為的保存代碼ButtonSelector被下面的私人DependencyProperty從而使Button被啟用和禁用,可以發現:

private static readonly DependencyProperty MoveUpButton = DependencyProperty.RegisterAttached("MoveUpButton", typeof(ButtonBase), typeof(ListHelperBehavior), new PropertyMetadata(null)); 

Add Item代碼不需要監視SelectionChanged事件,因為Button從不禁用它。
的Click事件Button下移功能如下:

private static void MoveItemUpEvent(object sender, RoutedEventArgs e) { Debug.Assert(sender is ButtonBase); var Button = (ButtonBase)sender; var Selector = GetMoveItemUp(Button); var IList = CheckForIList(Selector); var itemNumber = Selector.SelectedIndex; var item = IList[itemNumber]; IList.RemoveAt(itemNumber); var type = IList.GetType().GetGenericArguments().Single(); var castInstance = Convert.ChangeType(item, type); IList.Insert(itemNumber - 1, castInstance); if (itemNumber == 1) Button.IsEnabled = false; Selector.SelectedIndex = itemNumber - 1; } 

sender參數必須強制轉換為ButtonBase類型,然后用於獲取Selector作為ButtonBase中附加屬性保存控件的值然后使用它來獲取IList綁定到Selector ItemsSource DependencyPropertySelectedItemSelectorIList然后復制所選項目,轉換為正確的類型(使用Type類的Reflection GetGenericArgument方法獲取類型,然后使用Convert.ChangeType方法將其強制轉換),然后從IList(RemoveAt方法)中刪除IList)。然后使用該Selector Insert方法插入刪除的項目

接下來檢查是否現在是第一個項目,禁用Button它是否為,並且Selector SelectedIndex設置為仍然指向同一個項目。

碼幾乎是相同的,則刪除要簡單得多,因為它沒有保存已刪除的項目,然后將其放回IList

最后,有適當的代碼啟用或禁用Button取決於是否存在SelectedItemSelectedItem是第一個(用於上)或最后一個項目IList(用於下移)。這是SelectedItemSelector觸發事件時調用的事件處理程序

private static void SetMoveItemUpButtonIsEnabled(object sender, RoutedEventArgs e) { <code> Debug.Assert(sender is Selector); var Selector = (Selector)sender; var IList = CheckForIList(Selector); var itemNumber = Selector.SelectedIndex; var Button = (ButtonBase) Selector.GetValue(MoveUpButton); Button.IsEnabled = (itemNumber >= 1 && itemNumber < IList.Count); }</code> 

對於這種需要IList綁定到ItemsSourceSelectedIndex,並需要得到Button保存為一個附加屬性在此功能Selector對於Remove函數,只需要知道if SelectedIndex是否等於-1,這樣簡單得多。

使用行為

要使用此行為,只需要一個從Selector控件派生的列表控件,Name為此控件關聯一個值,並Button為每個應該實現的函數定義一個網站源碼。在每一個Button XAML只包括ListHelperBahaviorDependencyProperty它有關聯BindingSelector

<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <ListBox Name="TheList"              ItemsSource="{Binding List}"              HorizontalAlignment="Stretch"              VerticalAlignment="Stretch"  > <ListBox.ItemTemplate> <DataTemplate> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="30"/> <ColumnDefinition Width="200"/> </Grid.ColumnDefinitions> <TextBlock Text="{Binding ItemNumber}"/> <TextBlock Grid.Column="1"                                Text="{Binding TimeCreated}"/> </Grid> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <StackPanel Grid.Row="2"                 Margin="-5 5"                 Orientation="Horizontal"                 HorizontalAlignment="Right"> <Button Content="Add"                 Width="70"                 Margin="5"                 local:ListHelperBehavior.AddToList="{Binding ElementName=TheList}"/> <Button Content="Remove"                 Width="70"                 Margin="5"                 local:ListHelperBehavior.RemoveFromList="{Binding ElementName=TheList}"/> <Button Content="Move Up"                 Width="70"                 Margin="5"                 local:ListHelperBehavior.MoveItemUp="{Binding ElementName=TheList}"/> <Button Content="Move Down"                 Width="70"                 Margin="5"          local:ListHelperBehavior.MoveItemDown="{Binding ElementName=TheList}"/> </StackPanel> 

WPF行為的圖像2為按鈕提供了添加,刪除和重新排列ListBox內容的功能

問題

行為存在一些限制,其中一些可以使用其他代碼進行處理。
其中一個問題是行為預期綁定到該類型Selector的類型的IList,這意味着這兩個ListObservableCollection可使用,但Array Type不能。這可以編碼,但需要Array每次重新創建

另一個限制是Add只有Type在它IList是一個類時才有效,並且有一個默認的構造函數。

當然另一個限制是它只處理從控件派生的Selector控件。

結論

這是一個非常好的小行為,因為它允許更改列表的順序,並通過僅將行為添加Button到實現該功能的每個項目來添加或刪除項目ViewModel中無需任何操作即可提供此功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM