如何对 RibbonComboBox 的 SelectedItem 进行数据绑定 [英] How to databind SelectedItem of RibbonComboBox

查看:22
本文介绍了如何对 RibbonComboBox 的 SelectedItem 进行数据绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题基本上是这个.不过,我认为提供更多信息和代码有助于更轻松地重现问题.

My question is basically this one. I thought it would help to provide some more information and code that makes it easier to reproduce the problem, though.

使用来自 RibbonControlsLibrary 的 Microsoft.Windows.Controls.Ribbon.RibbonComboBox 感觉就像穿过一个充满虫子的大沼泽,如果你知道如何绕过它,你就不会这样做.

Working with the Microsoft.Windows.Controls.Ribbon.RibbonComboBox from the RibbonControlsLibrary feels like walking through a big bog full of bugs, not something you do if you know a way around it.

任何人.我遇到的最大问题是数据绑定我的 SelectedItem.

Anywho. The biggest problem I encountered was databinding my SelectedItem.

以下是我的开始(在我发现 RibbonGallery 之后?).在 ComboBox 的子元素上拥有 ItemsSource 和 SelectedItem 并且甚至不在同一级别已经给了我heebie-jeebies,但这似乎是正确的.

The following is what I started with (after I found out about RibbonGallery?). To have ItemsSource and SelectedItem on subelements of the ComboBox and not even on the same level already gave me the heebie-jeebies, but that seems to be correct.

在示例应用程序中,我在 ViewModel 的构造函数中设置 SelectedItem.但是,在运行应用程序时,不会显示 SelectedItem.甚至 VS 设计师也正确显示了第二个选项"!

In the example app, I'm setting the SelectedItem in the constructor of the ViewModel. However, when running the app, no SelectedItem is shown. Even the VS designer is correctly showing "second option"!

正在运行的应用程序: VS 设计器:

Running app: VS designer:

在调试 SelectedItem setter 时,您会注意到多次通过.在ctor(1,见下面的调试日志)中第一次将它设置为第二个选项"后,它将重置为空(2)(通过外部代码,我认为是控件本身).在 UI 中打开下拉菜单时,它将再次设置为 null (3),然后在选择一个值时,两次设置为该值 (4,5).我选择了第二个选项",然后用第一个选项"(6-9)重复了这个过程.这产生了以下日志(忽略功能区控件中的一千零一个绑定异常...):

When debugging the SelectedItem setter, you'll notice multiple passes. After setting it the first time to "second option" in the ctor(1, see debug log below), it will reset to null (2) (by external code, I reckon in the control itself). When opening the dropdown in the UI, it will be set to null again (3), then when selecting a value, twice to this value (4,5). I selected "second option", then repeated the procedure with "first option" (6-9). This produced the following log (ignoring the one thousand and one binding exceptions from the ribbon control...):

最大的问题显然是(2),它正在重置我的初始选择.看起来当控件第一次显示时,它被重置.一个非常丑陋的解决方法是通过计时器设置该值.在这个示例应用程序中,在用户控件的 Loaded 事件中设置它对我有用,但在我更重的现实生活应用程序中,它不起作用.无论如何,这一切都让人感觉不对.有人知道更好的解决方案吗?

The big problem obviously is (2), which is resetting my initial selection. Looks like when the control is shown the first time, it is reset. A very ugly workaround would be to set the value by a timer. Setting it in the Loaded event of the user control does work for me in this example app, but in my heavier real-life app, it does not. Anyway, all of that feels wrong. Does anyone know a better solution?

XML:

<UserControl x:Class="WpfApplication1.RibbonComboBoxDemo"
             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:r="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon" 
             xmlns:local="clr-namespace:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">

    <UserControl.DataContext>
        <local:ViewModel />
    </UserControl.DataContext>

    <Grid>
        <r:Ribbon >
            <r:RibbonTab Header="First Tab">
                <r:RibbonGroup Header="Group">
                    <r:RibbonComboBox >
                        <r:RibbonGallery SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
                            <r:RibbonGalleryCategory ItemsSource="{Binding Controls}" DisplayMemberPath="Caption" />
                        </r:RibbonGallery>
                    </r:RibbonComboBox>
                </r:RibbonGroup>
            </r:RibbonTab>
            <r:RibbonTab Header="Second Tab" />
        </r:Ribbon>
    </Grid>
</UserControl>

视图模型:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;

namespace WpfApplication1
{
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public ObservableCollection<ControlBaseModel> Controls { get; private set; }


        private ControlBaseModel _selectedItem;
        public ControlBaseModel SelectedItem { get { return _selectedItem; } set { LogSelectedItemChange(value); _selectedItem = value; OnPropertyChanged("SelectedItem"); } }

        public ViewModel()
        {
            this.Controls = new ObservableCollection<ControlBaseModel>();

            this.Controls.Add(new ControlBaseModel() { Caption = "first option" });
            this.Controls.Add(new ControlBaseModel() { Caption = "second option" });

            this.SelectedItem = this.Controls[1]; // set to second option
        }

        int i = 0;
        private void LogSelectedItemChange(ControlBaseModel value)
        {
            i++;
            string setObject = "null";
            if (value != null)
            {
                setObject = value.Caption;
            }
            Debug.WriteLine(string.Format("{0}: SelectedItem.set(): {1}", i, setObject));
        }

    }

    public class ControlBaseModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private string _name;
        public string Name { get { return _name; } set { _name = value; OnPropertyChanged("Name"); } }

        private string _caption;
        public string Caption { get { return _caption; } set { _caption = value; OnPropertyChanged("Caption"); } }
    }
}

推荐答案

虽然在我的应用程序中将 ComboBox SelectedItem 重置为 null 之前发生了 View/UserControl 加载事件,但实际上 ComboBox 加载事件被触发了两次,第二次时间晚"了.所以我目前的解决方案是:

While the View/UserControl loaded event is occuring before the ComboBox SelectedItem is reset to null in my application, the ComboBox loaded event is in fact fired twice, the second time "late" enough. So my current solution, which I will ditch gladly for a better one, is this:

<r:RibbonComboBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoadedCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <r:RibbonGallery SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
        <r:RibbonGalleryCategory ItemsSource="{Binding Controls}" DisplayMemberPath="Caption"/>
    </r:RibbonGallery>
</r:RibbonComboBox>

视图模型:

private ControlBaseModel _lastNonNullSelectedItem;

public ObservableCollection<ControlBaseModel> Controls { get; private set; }

private ControlBaseModel _selectedItem;
public ControlBaseModel SelectedItem 
{ 
    get { return _selectedItem; } 
    set 
    { 
        if (value != null) { _lastNonNullSelectedItem = value; } 
        _selectedItem = value; 
        OnPropertyChanged("SelectedItem"); 
    } 
}
public ICommand LoadedCommand { get; private set; }


public ViewModel()
{
    this.Controls = new ObservableCollection<ControlBaseModel>();
    this.LoadedCommand = new ActionCommand(OnLoaded); // ActionCommand: simple implementation of ICommand

    this.Controls.Add(new ControlBaseModel() { Caption = "first option" });
    this.Controls.Add(new ControlBaseModel() { Caption = "second option" });

    this.SelectedItem = this.Controls[1]; // set to second option
}

private void OnLoaded()
{
    this.SelectedItem = _lastNonNullSelectedItem;
}

这篇关于如何对 RibbonComboBox 的 SelectedItem 进行数据绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆