gpt4 book ai didi

c# - 如何从 PropertyChanged 事件中正确重置与 ComboBox 关联的值?

转载 作者:太空宇宙 更新时间:2023-11-03 15:09:07 25 4
gpt4 key购买 nike

我有一个 ComboBox绑定(bind)到我的 ViewModel 上的一个属性(从“VM”上听到)。当用户在 ComboBox 上进行选择时它会正确更新我的 VM 中的绑定(bind)属性。在我的 UI 代码中,我订阅了 PropertyChanged我的虚拟机上的事件。

正如它应该表现的那样,当用户在 ComboBox 中进行选择时, 我的 PropertyChanged事件在我的 UI 后端代码中正确执行。当 UI 代码捕捉到此属性的更改时,在某些选择条件下,我需要停止进程并请求用户提供更多信息。从 UI 中,我向他们发送了一个对话框。如果他们取消对话框,我会重置与 ComboBox 关联的 VM 中的值。控制 SelectedValue .

这是我观察到的。当用户取消操作时,我的 VM 属性被设置为新值。但是,ComboBox仍然显示现在已更改的原始条目的文本值。如何强制 ComboBox从我的PropertyChanged 中更新自己事件?在这种情况下,我认为这只是一个文本问题或数字索引更改,它引用了绑定(bind)集合中的文本数据。 VM 中的数据正确,但显示值为 ComboBox是错的。

示例

组合框详情

    <ComboBox
ItemsSource="{Binding ListOfComboBoxDisplayObjects}"
SelectedValue="{Binding MySelectionIsAnEnumeration}"
DisplayMemberPath="Text"
SelectedValuePath="EnumerationValue"
Height="27" />

对虚拟机上的冗长属性感到抱歉,但这是为了解释正在发生的事情。我的 ListOfComboBoxDisplayObjects collection 表示一组枚举器值,它们存储在 SelectedValuePath 内的路径中。 .每个值的描述性文本来自 ListOfComboBoxDisplayObjects这是一个为 UI 严格创建的特殊列表。这基本上将枚举值与有意义的描述配对。

ListOfComboBoxDisplayObjects 定义(来自 VM)

编辑 #1 - 将此定义添加到我的示例中
 private ObservableCollection<BindableEnumerationItem<Values>> _listOfComboBoxDisplayObjects;
public ObservableCollection<BindableEnumerationItem<Values>> ListOfComboBoxDisplayObjects
{
get { return _listOfComboBoxDisplayObjects; }
private set
{
if (value != _listOfComboBoxDisplayObjects)
{
_listOfComboBoxDisplayObjects= value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ListOfComboBoxDisplayObjects)));
}
}
}

MySelectionIsAnEnumeration 定义(来自 VM 内)

*编辑#1:添加此代码定义。
    private Values_mySelectionIsAnEnumeration ;
public Values MySelectionIsAnEnumeration
{
get { return _mySelectionIsAnEnumeration; }
set
{
//Double-checked this-- value is different on the second-call to change this value, once the UI cancels the operation.
if (value != _mySelectionIsAnEnumeration)
{
_mySelectionIsAnEnumeration= value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MySelectionIsAnEnumeration )));
}
}
}

与 ListOfComboBoxDisplayObjects 关联的相关值

这些值在 VM 的 ctor 中生成。它们在整个应用程序中都是固定的。

项目 #1
  • 文本:“这是一个 Foo!”
  • 值:Values.Foo

  • 项目#2:
  • 文本:“嗨,我是 Bar。”
  • 值:Values.Bar

  • 项目#3:
  • 文字:“这是巴兹。我需要问一个问题才能使用。”
  • 值(value):值(value)观.Baz

  • PropertyChanged 事件 - 来自 UI 后端
    private void VM_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
    switch (e.PropertyName)
    {
    case "MySelectionIsAnEnumeration":
    if (VM.MySelectionIsAnEnumeration == Values.Baz)
    {
    //Prompt the user and get DialogResult.
    bool answerGiven = AskAQuestionAndGetAResult();
    if(!answerGiven)
    VM.MySelectionIsAnEnumeration = Values.Foo;
    }
    break;
    }
    }

    执行上述代码后,我观察到 VM.MySelectionIsAnEnumeration value 确实正在更改为 Value.Foo 的正确值当用户在 AskAQuestionAndGetAResult() 内取消操作时.然而,在它完成后 ComboBox还是写着“This is Baz. I need to ask a question才可以使用。”,这显然是与 Value.Baz关联的显示值.

    如何更新基础 VM 属性和 CombobBox 上的显示文本正确显示现在存储在 VM.MySelectionIsAnEnumeration 中的值?

    编辑#2

    下面是我的 BindableEnumerationItem 的代码我在我的 Observable Collections 中用于组合框和列表框。这在我的整个应用程序中都在更简单的情况下使用,并且没有引起任何问题。请注意,这是我实际的、未更改的代码。我没有重命名任何东西。我的组合框可以绑定(bind)到每个 Item类型安全属性的属性和 DisplayText是描述 rune 本。
    public class BindableEnumerationItem<T> : INotifyPropertyChanged 
    {
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    private T _item;

    public BindableEnumerationItem(T item, string displayText)
    {
    _item = item;
    _displayText = displayText;
    }

    private string _displayText;
    public string DisplayText
    {
    get { return _displayText; }
    set
    {
    if (value != _displayText)
    {
    _displayText = value;
    PropertyChanged(this, new PropertyChangedEventArgs("DisplayText"));
    }
    }
    }

    public T Item
    {
    get { return _item; }
    set
    {
    _item = value;
    PropertyChanged(this, new PropertyChangedEventArgs("Item"));
    }
    }
    }

    最佳答案

    创建一个扩展,将 xaml 中的 View 模型中的命令连接到选择器,在本例中为组合框。

    public partial class Extensions
    {
    public static readonly DependencyProperty SelectionChangedCommandProperty = DependencyProperty.RegisterAttached("SelectionChangedCommand", typeof(ICommand), typeof(Extensions), new UIPropertyMetadata((s, e) =>
    {
    var element = s as Selector;

    if (element != null)
    {
    element.SelectionChanged -= OnSelectionChanged;

    if (e.NewValue != null)
    {
    element.SelectionChanged += OnSelectionChanged;
    }
    }
    }));

    public static ICommand GetSelectionChangedCommand(UIElement element)
    {
    return (ICommand)element.GetValue(SelectionChangedCommandProperty);
    }

    public static void SetSelectionChangedCommand(UIElement element, ICommand value)
    {
    element.SetValue(SelectionChangedCommandProperty, value);
    }

    private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    var element = sender as Selector;
    var command = element.GetValue(SelectionChangedCommandProperty) as ICommand;

    if (command != null && command.CanExecute(element.SelectedItem))
    {
    command.Execute(element.SelectedItem);
    e.Handled = true;
    }
    }
    }

    在处理值更改事件的 View 模型中创建命令。
    public ICommand EnumerationValueChangedCommand
    {
    get
    {
    return new Command(
    () =>
    {
    if (VM.MySelectionIsAnEnumeration == Values.Baz)
    {
    //Prompt the user and get DialogResult.
    bool answerGiven = AskAQuestionAndGetAResult();
    if (!answerGiven)
    VM.MySelectionIsAnEnumeration = Values.Foo;
    }
    });
    }
    }

    然后使用该扩展名进行绑定(bind)。 ext 是您的扩展的命名空间。
    <ComboBox
    ItemsSource="{Binding ListOfComboBoxDisplayObjects}"
    SelectedValue="{Binding MySelectionIsAnEnumeration}"
    DisplayMemberPath="Text"
    SelectedValuePath="EnumerationValue"
    ext:Extensions.SelectionChangedCommand="{Binding EnumerationValueChangedCommand}"
    Height="27" />

    关于c# - 如何从 PropertyChanged 事件中正确重置与 ComboBox 关联的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41958534/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com