开发者

I can't figure out: User Control with ComboBox bubbling up SelectionChanged event

I can't seem to get this working. It is easy with sliders and any controls which pass simple types, but I cannot seem to figure out how to bubble up a ComboBox SelectionChanged with its ComboBoxItem.

This always fails with:

InnerException: System.TypeInitializationException Message=The type initializer for 'Module.Dashboard.KpiComboBox' threw an exception. TypeName=Module.Dashboard.KpiC开发者_如何学JAVAomboBox InnerException: System.ArgumentException Message=Default value for the 'Value' property cannot be bound to a specific thread.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using PA.DPW.PACSES.CAL.Infrastructure;

namespace Module.Dashboard
{
    /// <summary>
    /// Interaction logic for KpiComboBox.xaml
    /// </summary>
    public partial class KpiComboBox : UserControl
    {
        public KpiComboBox()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Called to bind the proper KPIs to the cboKpi, according to which View name you pass
        /// </summary>
        /// <param name="viewName">Use Constants viewnames</param>
        /// <example>
        /// kpiComboBox.BindComboBox(Constants.CountyMapViewName);
        /// </example>
        public void BindComboBox(string viewName)
        {
            List<KPICodeDescription> lstKpi = null;

            switch (viewName)
            {
                case Constants.CountyMapViewName:
                    lstKpi = UtilityHelper.GetKpiList(Constants.CountyMapViewName);
                    break;
                case Constants.CountyRankingsViewName:
                    lstKpi = UtilityHelper.GetKpiList(Constants.CountyRankingsViewName);
                    break;
                case Constants.StateMapViewName:
                    lstKpi = UtilityHelper.GetKpiList(Constants.StateMapViewName);
                    break;
                case Constants.StateRankingsViewName:
                    lstKpi = UtilityHelper.GetKpiList(Constants.StateRankingsViewName);
                    break;
                default:
                    break;
            }

            if (lstKpi != null)
            {
                cboKpi2.ItemsSource = lstKpi;
                cboKpi2.DisplayMemberPath = "KPIDescription";
                cboKpi2.SelectedValuePath = "KPICode";
            }
        }

        // Dependency Object for Bubbling

        private ComboBoxItem value;

        public ComboBoxItem Value
        {
            get { return (ComboBoxItem)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        private static void OnSelectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            KpiComboBox cboControl = (KpiComboBox)sender;

            cboControl.value = (ComboBoxItem)args.NewValue;
            cboControl.OnSelectionChanged((ComboBoxItem)args.OldValue, (ComboBoxItem)args.NewValue);
        }

        public static readonly DependencyProperty ValueProperty =
           DependencyProperty.Register("Value", typeof(object), typeof(KpiComboBox), new PropertyMetadata(new Object(), OnSelectionChanged));
           //DependencyProperty.Register("Value", typeof(ComboBoxItem), typeof(KpiComboBox));

        // Event Bubbling

        public static readonly RoutedEvent SelectionChangedEvent =
           EventManager.RegisterRoutedEvent("SelectionChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(KpiComboBox));


        // Provide CLR accessors for the event
        public event RoutedPropertyChangedEventHandler<ComboBoxItem> SelectionChanged
        {
            add { AddHandler(SelectionChangedEvent, value); }
            remove { RemoveHandler(SelectionChangedEvent, value); }
        }

        private void OnSelectionChanged(ComboBoxItem oldValue, ComboBoxItem newValue)
        {
            RoutedPropertyChangedEventArgs<ComboBoxItem> args = new RoutedPropertyChangedEventArgs<ComboBoxItem>(oldValue, newValue);
            args.RoutedEvent =  KpiComboBox.SelectionChangedEvent;
            RaiseEvent(args);
        }

        // This method raises the SelectionChanged event
        void RaiseSelectionChangedEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(KpiComboBox.SelectionChangedEvent);
            RaiseEvent(newEventArgs);
        }

        private void cboKpi2_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            MessageBox.Show("Hello from UC");
            RaiseSelectionChangedEvent();
            //cboKpi2.SelectedItem =;
        }
    }
}


Well, the short answer would be did you try replacing

DependencyProperty.Register("Value", typeof(object), typeof(KpiComboBox), new PropertyMetadata(new Object(), OnSelectionChanged));

with

DependencyProperty.Register("Value", typeof(ComboBoxItem), typeof(KpiComboBox), new PropertyMetadata(null, OnSelectionChanged));

?

However, I fail to see why that's necessary - isn't ComboBox.SelectionChanged already a routed event? Meaning you can listen for it at any level, regardless of the type of actual control, if somewhere down the hierarchy you have ComboBox? Also, there are even easier ways to do it, if you're using MVVM. Go on, ask me more, I could go on for hours :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜