선택한 ComboBox 항목에 사용할 이벤트 처리기(선택한 항목을 반드시 변경할 필요는 없음)
목표: 콤보 상자 드롭다운 목록에서 항목을 선택하면 이벤트를 실행합니다.
문제:그러나 "Selection Changed"를 사용하면 현재 선택 중인 항목과 동일한 항목을 선택한 경우 선택이 변경되지 않으므로 이 이벤트가 트리거되지 않습니다.
질문:마우스가 해당 항목을 클릭하고 해당 항목이 선택되고 있는 한 선택한 항목에 관계없이 이벤트를 실행하는 데 사용할 수 있는 다른 이벤트 처리기(또는 다른 방법)
(명확성: 문제는 동일한 항목을 다시 선택할 때 "무언가"를 트리거하는 방법입니다.드롭다운 목록에 중복 항목이 없습니다.시나리오: 처음 항목 1을 선택한 후 드롭다운을 닫습니다.그런 다음 드롭다운 상자를 열고 일부 기능이 트리거되면 항목 1을 선택합니다.)
해결책: 현재로서는 이를 위한 직접적인 해결책이 없는 것 같습니다.하지만 각각의 프로젝트에 따라 해결할 수 있는 방법이 있을 수 있습니다. (정말 좋은 방법이 있는지 업데이트 부탁드립니다.)감사해요.
저는 같은 질문을 했고 마침내 답을 찾았습니다.
다음과 같이 SelectionChanged 이벤트와 DropDownClosed 이벤트를 모두 처리해야 합니다.
XAML에서:
<ComboBox Name="cmbSelect" SelectionChanged="ComboBox_SelectionChanged" DropDownClosed="ComboBox_DropDownClosed">
<ComboBoxItem>1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
</ComboBox>
C#에서:
private bool handle = true;
private void ComboBox_DropDownClosed(object sender, EventArgs e) {
if(handle)Handle();
handle = true;
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
ComboBox cmb = sender as ComboBox;
handle = !cmb.IsDropDownOpen;
Handle();
}
private void Handle() {
switch (cmbSelect.SelectedItem.ToString().Split(new string[] { ": " }, StringSplitOptions.None).Last())
{
case "1":
//Handle for the first combobox
break;
case "2":
//Handle for the second combobox
break;
case "3":
//Handle for the third combobox
break;
}
}
나를 위해.ComboBox.DropDownClosed
이벤트가 해냈습니다.
private void cbValueType_DropDownClosed(object sender, EventArgs e)
{
if (cbValueType.SelectedIndex == someIntValue) //sel ind already updated
{
// change sel Index of other Combo for example
cbDataType.SelectedIndex = someotherIntValue;
}
}
"ComboBoxItem"을 사용할 수 있습니다.마우스 아래쪽 미리 보기 이벤트입니다.따라서 마우스가 특정 항목을 누를 때마다 이 이벤트가 실행됩니다.
XAML에서 이 이벤트를 추가하려면 "ComboBox"를 사용합니다.ItemContainerStyle"은 다음 예와 같습니다.
<ComboBox x:Name="MyBox"
ItemsSource="{Binding MyList}"
SelectedValue="{Binding MyItem, Mode=OneWayToSource}" >
<ComboBox.ItemContainerStyle>
<Style>
<EventSetter Event="ComboBoxItem.PreviewMouseDown"
Handler="cmbItem_PreviewMouseDown"/>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
그리고 평소대로 처리합니다.
void cmbItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
//...do your item selection code here...
}
MSDN 덕분에
다음과 같은 요령으로 도움이 되길 바랍니다.
두 이벤트를 모두 바인딩할 수 있습니다.
combobox.SelectionChanged += OnSelectionChanged;
combobox.DropDownOpened += OnDropDownOpened;
선택한 항목을 OnDropDownOpened 내에서 null로 강제 설정
private void OnDropDownOpened(object sender, EventArgs e)
{
combobox.SelectedItem = null;
}
그리고 OnSelection Changed 안에 있는 항목으로 필요한 작업을 수행합니다.OnSelectionChanged(OnSelectionChanged)는 콤보 상자를 열 때마다 표시되지만 Selected(선택됨) 여부를 확인할 수 있습니다.메서드 내부의 항목이 null이고 명령을 건너뜁니다.
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (combobox.SelectedItem != null)
{
//Do something with the selected item
}
}
UWP(Windows Store) 앱의 경우 위의 항목이 작동하지 않습니다(PointerPressed가 실행되지 않고 미리 보기, 드롭다운 닫힘 또는 선택됨).IndexChanged 이벤트가 있음)
콤보박스 위에 투명 버튼을 올려놓아야 했습니다(드롭다운 화살표는 제외).화살표를 누르면 목록이 평소처럼 아래로 떨어지고 콤보 상자의 선택 변경 이벤트가 실행됩니다.콤보 상자의 다른 곳을 클릭하면 투명 단추의 클릭 이벤트가 실행되어 콤보 상자의 현재 값을 다시 선택할 수 있습니다.
일부 작동 중인 XAML 코드:
<Grid x:Name="ComboOverlay" Margin="0,0,5,0"> <!--See comments in code behind at ClickedComboButValueHasntChanged event handler-->
<ComboBox x:Name="NewFunctionSelect" Width="97" ItemsSource="{x:Bind Functions}"
SelectedItem="{x:Bind ChosenFunction}" SelectionChanged="Function_SelectionChanged"/>
<Button x:Name="OldFunctionClick" Height="30" Width="73" Background="Transparent" Click="ClickedComboButValueHasntChanged"/>
</Grid>
일부 작동 중인 C# 코드:
/// <summary>
/// It is impossible to simply click a ComboBox to select the shown value again. It always drops down the list of options but
/// doesn't raise SelectionChanged event if the value selected from the list is the same as before
///
/// To handle this, a transparent button is overlaid over the ComboBox (but not its dropdown arrow) to allow reselecting the old value
/// Thus clicking over the dropdown arrow allows the user to select a new option from the list, but
/// clicking anywhere else in the Combo re-selects the previous value
/// </summary>
private void ClickedComboButValueHasntChanged(object sender, RoutedEventArgs e)
{
//You could also dummy up a SelectionChangedEvent event and raise it to invoke Function_SelectionChanged handler, below
FunctionEntered(NewFunctionSelect.SelectedValue as string);
}
private void Function_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
FunctionEntered(e.AddedItems[0] as string);
}
시도할 수 있습니다.SelectedIndexChanged
동일한 항목을 선택한 경우에도 이벤트가 트리거됩니다.
UWP의 경우, 저는 다른 접근법을 시도했습니다.ComboBox 클래스를 확장하고 ComboBox의 SelectionChanged 및 OnKeyUp 이벤트와 ComboBox Items의 Tapped 이벤트를 처리했습니다.먼저 SelectionChanged(선택 변경)를 받지 않고 Tapped(탭됨) 이벤트 또는 Enter(입력) 또는 Space(공간) 키를 받은 경우 현재 항목이 다시 선택되었음을 알고 그에 따라 응답합니다.
class ExtendedComboBox : ComboBox
{
public ExtendedComboBox()
{
SelectionChanged += OnSelectionChanged;
}
protected override void PrepareContainerForItemOverride(Windows.UI.Xaml.DependencyObject element, object item)
{
ComboBoxItem cItem = element as ComboBoxItem;
if (cItem != null)
{
cItem.Tapped += OnItemTapped;
}
base.PrepareContainerForItemOverride(element, item);
}
protected override void OnKeyUp(KeyRoutedEventArgs e)
{
// if the user hits the Enter or Space to select an item, then consider this a "reselect" operation
if ((e.Key == Windows.System.VirtualKey.Space || e.Key == Windows.System.VirtualKey.Enter) && !isSelectionChanged)
{
// handle re-select logic here
}
isSelectionChanged = false;
base.OnKeyUp(e);
}
// track whether or not the ComboBox has received a SelectionChanged notification
// in cases where it has not yet we get a Tapped or KeyUp notification we will want to consider that a "re-select"
bool isSelectionChanged = false;
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
isSelectionChanged = true;
}
private void OnItemTapped(object sender, TappedRoutedEventArgs e)
{
if (!isSelectionChanged)
{
// indicates that an item was re-selected - handle logic here
}
isSelectionChanged = false;
}
}
private void OnDropDownClosed(object sender, EventArgs e)
{
if (combobox.SelectedItem == null) return;
// Do actions
}
이 문제는 해결책이 하나도 없었기 때문에 오랫동안 저를 괴롭힙니다 :(
하지만 좋은 소식은, 다음과 같은 방법이 제 지원서에 잘 적용된다는 것입니다.
기본 아이디어는 등록하는 것입니다.EventManager
에App.xmal.cs
냄새를 맡다PreviewMouseLeftButtonDownEvent
절대로ComboBoxItem
그런 다음 트리거링합니다.SelectionChangedEvent
선택 항목이 선택한 항목과 동일한 경우, 즉 인덱스를 변경하지 않고 선택이 수행됩니다.
인App.xmal.cs
:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// raise selection change event even when there's no change in index
EventManager.RegisterClassHandler(typeof(ComboBoxItem), UIElement.PreviewMouseLeftButtonDownEvent,
new MouseButtonEventHandler(ComboBoxSelfSelection), true);
base.OnStartup(e);
}
private static void ComboBoxSelfSelection(object sender, MouseButtonEventArgs e)
{
var item = sender as ComboBoxItem;
if (item == null) return;
// find the combobox where the item resides
var comboBox = ItemsControl.ItemsControlFromItemContainer(item) as ComboBox;
if (comboBox == null) return;
// fire SelectionChangedEvent if two value are the same
if ((string)comboBox.SelectedValue == (string)item.Content)
{
comboBox.IsDropDownOpen = false;
comboBox.RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, new ListItem(), new ListItem()));
}
}
}
그런 다음 모든 콤보 상자에 대해 등록합니다.SelectionChangedEvent
일반적인 방법으로:
<ComboBox ItemsSource="{Binding BindList}"
SelectionChanged="YourSelectionChangedEventHandler"/>
이제 두 인덱스가 다를 경우 일반적인 이벤트 처리 프로세스 외에는 특별한 것이 없습니다. 두 인덱스가 동일할 경우 항목의 마우스 이벤트가 먼저 처리되어 트리거됩니다.SelectionChangedEvent
이런 식으로 두 상황 모두가SelectionChangedEvent
:)
ComboBox에 연결하기 위한 종속성 개체입니다.
드롭다운이 열릴 때 현재 선택된 항목을 기록한 다음, 드롭다운이 닫혔을 때 동일한 인덱스가 여전히 선택된 경우 SelectionChanged 이벤트를 실행합니다.키보드 선택과 함께 작동하려면 수정이 필요할 수 있습니다.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Web.UI.WebControls;
namespace MyNamespace
{
public class ComboAlwaysFireSelection : DependencyObject
{
public static readonly DependencyProperty ActiveProperty = DependencyProperty.RegisterAttached(
"Active",
typeof(bool),
typeof(ComboAlwaysFireSelection),
new PropertyMetadata(false, ActivePropertyChanged));
private static void ActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as ComboBox;
if (element == null)
return;
if ((e.NewValue as bool?).GetValueOrDefault(false))
{
element.DropDownClosed += ElementOnDropDownClosed;
element.DropDownOpened += ElementOnDropDownOpened;
}
else
{
element.DropDownClosed -= ElementOnDropDownClosed;
element.DropDownOpened -= ElementOnDropDownOpened;
}
}
private static void ElementOnDropDownOpened(object sender, EventArgs eventArgs)
{
_selectedIndex = ((ComboBox) sender).SelectedIndex;
}
private static int _selectedIndex;
private static void ElementOnDropDownClosed(object sender, EventArgs eventArgs)
{
var comboBox = ((ComboBox) sender);
if (comboBox.SelectedIndex == _selectedIndex)
{
comboBox.RaiseEvent(new SelectionChangedEventArgs(Selector.SelectionChangedEvent, new ListItemCollection(), new ListItemCollection()));
}
}
[AttachedPropertyBrowsableForChildrenAttribute(IncludeDescendants = false)]
[AttachedPropertyBrowsableForType(typeof(ComboBox))]
public static bool GetActive(DependencyObject @object)
{
return (bool)@object.GetValue(ActiveProperty);
}
public static void SetActive(DependencyObject @object, bool value)
{
@object.SetValue(ActiveProperty, value);
}
}
}
액세스할 수 있도록 네임스페이스 접두사를 추가합니다.
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ut="clr-namespace:MyNamespace" ></UserControl>
그런 다음 그렇게 부착해야 합니다.
<ComboBox ut:ComboAlwaysFireSelection.Active="True" />
사용하다SelectionChangeCommitted(object sender, EventArgs e)
여기서의
모든 ComboBoxItem 인스턴스에는 미리 보기가 있습니다.마우스 다운 이벤트입니다.모든 ComboBoxItem에서 이 이벤트에 대한 사용자 지정 핸들러를 구독하면 드롭다운 목록의 모든 클릭을 처리할 수 있습니다.
// Subscribe on ComboBoxItem-s events.
comboBox.Items.Cast<ComboBoxItem>().ToList().ForEach(i => i.PreviewMouseDown += ComboBoxItem_PreviewMouseDown);
private void ComboBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
// your handler logic...
}
쉬워요, 그냥 if (e)를 추가하세요.항목 추가.카운트 == 0) 반환, 기능 시작 시 다음과 같이 반환됩니다.
private void ComboBox_Symbols_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0)
return;
//Some Other Codes
}
언급URL : https://stackoverflow.com/questions/16966264/what-event-handler-to-use-for-combobox-item-selected-selected-item-not-necessar
'it-source' 카테고리의 다른 글
브라우저가 요청을 취소하는 경우 ASP.NET Web API OperationCancelledException (0) | 2023.05.21 |
---|---|
SQL Server와 같은 join in from 절을 사용하여 select 절에서 Postgresql 하위 쿼리를 수행하는 방법은 무엇입니까? (0) | 2023.05.21 |
process.cwd()와 __dirname의 차이점은 무엇입니까? (0) | 2023.05.21 |
PowerShell에서 경로 다시 로드 (0) | 2023.05.21 |
MVC 레이저 마크업에서 쿼리 문자열 매개 변수를 가져오는 방법은 무엇입니까? (0) | 2023.05.21 |