Created
January 8, 2023 13:10
-
-
Save BYJRK/37d6df1c9f1d198f73538c5167d50f6a to your computer and use it in GitHub Desktop.
SelectedItemBehavior
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Xaml.Behaviors; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Data; | |
namespace WpfTutorials.RadioButtonBindings.Behaviors; | |
/// <summary> | |
/// Allows a <see cref="Panel"/> or <see cref="ItemsControl"/> to have a <see cref="ComboBox"/>-like behavior | |
/// that has a <see cref="SelectedItem"/> dependency property to be bound to a property in view model | |
/// </summary> | |
/// <example> | |
/// <code lang="xaml"> | |
/// <![CDATA[ | |
/// xmlns:i="http://schemas.microsoft.com/xaml/behaviors" | |
/// xmlns:be="clr-namespace:WpfTutorials.RadioButtonBindings.Behaviors" | |
/// | |
/// <StackPanel> | |
/// <i:Interaction.Behaviors> | |
/// <be:SelectedItemBehavior SelectedItem="{Binding SelectedItem}" /> | |
/// </i:Interaction.Behaviors> | |
/// <RadioButton Tag="A" /> | |
/// <RadioButton Tag="B" /> | |
/// <RadioButton Tag="C" /> | |
/// </StackPanel> | |
/// ]]> | |
/// </code> | |
/// </example> | |
public class SelectedItemBehavior : Behavior<FrameworkElement> | |
{ | |
#region SelectedItem Dependency Property | |
public object SelectedItem | |
{ | |
get => GetValue(SelectedItemProperty); | |
set => SetValue(SelectedItemProperty, value); | |
} | |
/// <summary> | |
/// The <see cref="SelectedItem"/> within this <see cref="Panel"/> or <see cref="ItemsControl"/> | |
/// </summary> | |
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( | |
nameof(SelectedItem), | |
typeof(object), | |
typeof(SelectedItemBehavior), | |
new PropertyMetadata(null, OnSelectedItemChanged) | |
); | |
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |
{ | |
var behavior = Interaction.GetBehaviors(d).OfType<SelectedItemBehavior>().FirstOrDefault(); | |
if (behavior is null) return; | |
foreach (var child in behavior.Children) | |
{ | |
child.IsChecked = child.Tag.Equals(e.NewValue); | |
} | |
} | |
#endregion | |
protected override void OnAttached() | |
{ | |
AssociatedObject.Loaded += OnAssociatedLoaded; | |
} | |
protected override void OnDetaching() | |
{ | |
AssociatedObject.Loaded -= OnAssociatedLoaded; | |
foreach (var child in Children) | |
{ | |
child.Checked -= OnRadioButtonChecked; | |
} | |
} | |
private void OnAssociatedLoaded(object? sender, RoutedEventArgs e) | |
{ | |
foreach (var child in Children) | |
{ | |
child.Checked += OnRadioButtonChecked; | |
child.IsChecked = child.Tag.Equals(SelectedItem); | |
} | |
} | |
private void OnRadioButtonChecked(object sender, RoutedEventArgs e) | |
{ | |
var radio = sender as RadioButton; | |
SelectedItem = radio!.Tag; | |
BindingOperations.GetBindingExpression(this, SelectedItemProperty).UpdateSource(); | |
} | |
/// <summary> | |
/// Enumerate all <see cref="RadioButton"/> children of the <see cref="Behavior{T}.AssociatedObject"/> | |
/// </summary> | |
private IEnumerable<RadioButton> Children => AssociatedObject switch | |
{ | |
Panel panel => panel.Children.OfType<RadioButton>(), | |
ItemsControl control => control.Items.OfType<RadioButton>(), | |
_ => Enumerable.Empty<RadioButton>(), | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Interaction.GetBehaviors(d).OfType().FirstOrDefault(); 经常返回空