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

查看:181
本文介绍了如何数据绑定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.

使用Microsoft.Windows.Controls.Ribbon.RibbonComboBox来自 RibbonControlsLibrary 的感觉就像穿过一个充满臭虫的大沼泽地,而不是如果你知道一些方法,你会做些什么。

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.

Anywho。遇到的最大问题是数据绑定我的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设置器时,会注意到多遍。第一次在ctor中设置第二个选项(1,参见下面的调试日志),它将重置为null(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),这是重新设置我的初始选择。看起来当第一次显示控件时,它被重置。一个非常丑的解决方法是通过计时器设置值。在用户控件的加载事件中设置它在本示例应用程序中对我有用,但在我更重的现实生活中,它不会。无论如何,所有这一切都感觉错了。有没有人知道更好的解决方案?

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?

Xaml:

<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>

ViewModel:

ViewModel:

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>

ViewModel:

ViewModel:

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天全站免登陆