Подтвердить что ты не робот

Отменить выделение выделенных полей в WPF с MVVM

У меня есть combobox в моем приложении WPF:

<ComboBox  ItemsSource="{Binding CompetitorBrands}" DisplayMemberPath="Value" 
   SelectedValuePath="Key" SelectedValue="{Binding Path=CompMfgBrandID, Mode=TwoWay,
   UpdateSourceTrigger=PropertyChanged}" Text="{Binding CompMFGText}"/>

Связано с набором KeyValuePair<string, string>

Вот свойство CompMfgBrandID в моей модели ViewModel:

public string CompMfgBrandID
{
    get { return _compMFG; }
    set
    {    
        if (StockToExchange != null && StockToExchange.Where(x => !string.IsNullOrEmpty(x.EnteredPartNumber)).Count() > 0)
        {
            var dr = MessageBox.Show("Changing the competitor manufacturer will remove all entered parts from the transaction.  Proceed?",
                "Transaction Type", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
            if (dr != DialogResult.Yes)
                return;
        }

        _compMFG = value;
        StockToExchange.Clear();

        ...a bunch of other functions that don't get called when you click 'No'...
        OnPropertyChanged("CompMfgBrandID");
    }
}

Если вы выберете "да", он будет вести себя так, как ожидалось. Элементы очищаются и вызывается остальные функции. Если я выберу "Нет", он вернется и не очистит мой список или вызовет любую из других функций, что хорошо, но combobox все еще отображает новый выбор. Мне нужно, чтобы он вернулся к исходному выбору, как будто ничего не изменилось, когда пользователь выбрал "Нет". Как я могу это сделать? Я также попытался добавить e.Handled = true в codebehind, безрезультатно.

4b9b3361

Ответ 1

Чтобы добиться этого при MVVM....

1] Привяжите поведение, которое обрабатывает событие SelectionChanged для ComboBox. Это событие возникает с некоторыми аргументами событий, которые имеют флаг Handled. Но привязка к true бесполезно для привязки SelectedValue. Источник связывания обновлений независимо от того, было ли обработано событие.

2] Поэтому мы настраиваем привязку ComboBox.SelectedValue как TwoWay и Explicit.

3] Только когда выполняется проверка, а в сообщении-сообществе указано Yes, когда мы выполняем BindingExpression.UpdateSource(). В противном случае мы просто вызываем BindingExpression.UpdateTarget() для возврата к предыдущему выбору.


В моем примере ниже у меня есть список KeyValuePair<int, int>, привязанный к контексту данных окна. ComboBox.SelectedValue привязан к простому записываемому свойству MyKey Window.

XAML...

    <ComboBox ItemsSource="{Binding}"
              DisplayMemberPath="Value"
              SelectedValuePath="Key"
              SelectedValue="{Binding MyKey,
                                      ElementName=MyDGSampleWindow,
                                      Mode=TwoWay,
                                      UpdateSourceTrigger=Explicit}"
              local:MyAttachedBehavior.ConfirmationValueBinding="True">
    </ComboBox>

Где MyDGSampleWindow - это x: Имя Window.

Код за...

public partial class Window1 : Window
{
    private List<KeyValuePair<int, int>> list1;

    public int MyKey
    {
        get; set;
    }

    public Window1()
    {
        InitializeComponent();

        list1 = new List<KeyValuePair<int, int>>();
        var random = new Random();
        for (int i = 0; i < 50; i++)
        {
            list1.Add(new KeyValuePair<int, int>(i, random.Next(300)));
        }

        this.DataContext = list1;
    }
 }

И прикрепленное поведение

public static class MyAttachedBehavior
{
    public static readonly DependencyProperty
        ConfirmationValueBindingProperty
            = DependencyProperty.RegisterAttached(
                "ConfirmationValueBinding",
                typeof(bool),
                typeof(MyAttachedBehavior),
                new PropertyMetadata(
                    false,
                    OnConfirmationValueBindingChanged));

    public static bool GetConfirmationValueBinding
        (DependencyObject depObj)
    {
        return (bool) depObj.GetValue(
                        ConfirmationValueBindingProperty);
    }

    public static void SetConfirmationValueBinding
        (DependencyObject depObj,
        bool value)
    {
        depObj.SetValue(
            ConfirmationValueBindingProperty,
            value);
    }

    private static void OnConfirmationValueBindingChanged
        (DependencyObject depObj,
        DependencyPropertyChangedEventArgs e)
    {
        var comboBox = depObj as ComboBox;
        if (comboBox != null && (bool)e.NewValue)
        {
            comboBox.Tag = false;
            comboBox.SelectionChanged -= ComboBox_SelectionChanged;
            comboBox.SelectionChanged += ComboBox_SelectionChanged;
        }
    }

    private static void ComboBox_SelectionChanged(
        object sender, SelectionChangedEventArgs e)
    {
        var comboBox = sender as ComboBox;
        if (comboBox != null && !(bool)comboBox.Tag)
        {
            var bndExp
                = comboBox.GetBindingExpression(
                    Selector.SelectedValueProperty);

            var currentItem
                = (KeyValuePair<int, int>) comboBox.SelectedItem;

            if (currentItem.Key >= 1 && currentItem.Key <= 4
                && bndExp != null)
            {
                var dr
                    = MessageBox.Show(
                        "Want to select a Key of between 1 and 4?",
                        "Please Confirm.",
                        MessageBoxButton.YesNo,
                        MessageBoxImage.Warning);
                if (dr == MessageBoxResult.Yes)
                {
                    bndExp.UpdateSource();
                }
                else
                {
                    comboBox.Tag = true;
                    bndExp.UpdateTarget();
                    comboBox.Tag = false;
                }
            }
        }
    }
}

В поведении я использую свойство ComboBox.Tag для временного хранения флага, который пропускает повторную проверку, когда мы возвращаемся к старому выбранному значению.

Сообщите мне, если это поможет.

Ответ 2

Очень простое решение для .NET 4.5. 1+:

<ComboBox SelectedItem="{Binding SelectedItem, Delay=10}" ItemsSource="{Binding Items}"  />

Это работает для меня во всех случаях. Вы можете откатить выделение в выпадающем списке, просто запустите NotifyPropertyChanged без присвоения значения.

Ответ 3

Это может быть достигнуто общим и компактным способом, используя Blend Generic Behavior.

Поведение определяет свойство зависимостей с именем SelectedItem, и вы должны поместить свою привязку в это свойство, а не в свойство ComboBox SelectedItem. Поведение отвечает за передачу изменений в свойстве зависимостей в ComboBox (или, более широко, в Селектор), и когда селектор SelectedItem изменяется, он пытается присвоить его собственному свойству SelectedItem. Если присваивание не выполняется (вероятно, из-за того, что связанный установщик pro proprity VM отклонил назначение), поведение обновляет Selectors SelectedItem с текущим значением его свойства SelectedItem.

По разным причинам вы можете столкнуться с ситуациями, когда список элементов в Селекторе очищается, а выбранный элемент становится нулевым (см. этот вопрос). Обычно вы не хотите, чтобы ваше свойство VM стало нулевым в этом случае. Для этого я добавил свойство зависимостей IgnoreNullSelection, которое по умолчанию является истинным. Это должно решить эту проблему.

Это класс CancellableSelectionBehavior:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Interactivity;

namespace MySampleApp
{
    internal class CancellableSelectionBehavior : Behavior<Selector>
    {
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.SelectionChanged += OnSelectionChanged;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.SelectionChanged -= OnSelectionChanged;
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(CancellableSelectionBehavior),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemChanged));

        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public static readonly DependencyProperty IgnoreNullSelectionProperty =
            DependencyProperty.Register("IgnoreNullSelection", typeof(bool), typeof(CancellableSelectionBehavior), new PropertyMetadata(true));

        /// <summary>
        /// Determines whether null selection (which usually occurs since the combobox is rebuilt or its list is refreshed) should be ignored.
        /// True by default.
        /// </summary>
        public bool IgnoreNullSelection
        {
            get { return (bool)GetValue(IgnoreNullSelectionProperty); }
            set { SetValue(IgnoreNullSelectionProperty, value); }
        }

        /// <summary>
        /// Called when the SelectedItem dependency property is changed.
        /// Updates the associated selector SelectedItem with the new value.
        /// </summary>
        private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (CancellableSelectionBehavior)d;

            // OnSelectedItemChanged can be raised before AssociatedObject is assigned
            if (behavior.AssociatedObject == null)
            {
                System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
                {
                    var selector = behavior.AssociatedObject;
                    selector.SelectedValue = e.NewValue;
                }));
            }
            else
            {
                var selector = behavior.AssociatedObject;
                selector.SelectedValue = e.NewValue;
            }
        }

        /// <summary>
        /// Called when the associated selector selection is changed.
        /// Tries to assign it to the <see cref="SelectedItem"/> property.
        /// If it fails, updates the selector with  <see cref="SelectedItem"/> property current value.
        /// </summary>
        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (IgnoreNullSelection && (e.AddedItems == null || e.AddedItems.Count == 0)) return;
            SelectedItem = AssociatedObject.SelectedItem;
            if (SelectedItem != AssociatedObject.SelectedItem)
            {
                AssociatedObject.SelectedItem = SelectedItem;
            }
        }
    }
}

Это способ использовать его в XAML:

<Window x:Class="MySampleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="My Smaple App" Height="350" Width="525"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:MySampleApp"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        mc:Ignorable="d"
        d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
    <StackPanel>
        <ComboBox ItemsSource="{Binding Options}">
            <i:Interaction.Behaviors>
                <local:CancellableSelectionBehavior SelectedItem="{Binding Selected}" />
            </i:Interaction.Behaviors>
        </ComboBox>
    </StackPanel>
</Window>

и это образец свойства VM:

private string _selected;

public string Selected
{
    get { return _selected; }
    set
    {
        if (IsValidForSelection(value))
        {
            _selected = value;
        }
    }
}

Ответ 4

Я нашел гораздо более простой ответ на этот вопрос пользователем shaun в другом потоке: fooobar.com/questions/234869/...

Основная проблема заключается в том, что свойство с измененным событием проглатывается. Некоторые назвали бы это ошибкой. Чтобы обойти это, используйте BeginInvoke из Диспетчера, чтобы принудительно изменить событие изменения свойства, чтобы вернуть его в конец очереди событий пользовательского интерфейса. Это не требует изменений для xaml, никаких дополнительных классов поведения, а одна строка кода изменена на модель представления.

Ответ 5

Проблема заключается в том, что, как только WPF обновляет значение с помощью setterter свойств, он игнорирует любое другое свойство, измененное уведомлениями внутри этого вызова: он предполагает, что они будут выполняться как нормальная часть setter и не имеют никакого значения, даже если вы действительно обновили свойство до исходного значения.

То, как я обошел это, - это разрешить обновлению поля, но также поставить в очередь действие на Диспетчере, чтобы "отменить" изменение. Действие вернет его к старому значению и вызовет уведомление об изменении свойства, чтобы WPF понял, что это не действительно новое значение, которое, по его мнению, было.

Очевидно, что действие "отменить" должно быть настроено таким образом, чтобы он не запускал какую-либо бизнес-логику в вашей программе.

Ответ 6

У меня была одна и та же проблема, вызванная потоком пользовательского интерфейса и тем, как работает biding. Проверьте эту ссылку: SelectedItem на ComboBox

Структура в образце использует код позади, но MVVM точно такой же.

Ответ 7

Я предпочитаю образец кода "splinteror" над "AngelWPF's". Однако их подходы довольно схожи. Я применил приложенное поведение, CancellableSelectionBehavior, и оно работает как рекламируемое. Возможно, именно код в примере splintor был проще подключить к моему приложению. Код, связанный с приложением AngelWPF, имел ссылки на тип KeyValuePair, который потребовал бы большего изменения кода.

В моем приложении у меня был ComboBox, где элементы, отображаемые в DataGrid, основаны на элементе, выбранном в ComboBox. Если пользователь внес изменения в DataGrid, а затем выбрал новый элемент в ComboBox, я бы попросил пользователя сохранить изменения с помощью кнопок "Да", "NO | Отмена" в качестве параметров. Если они нажали "Отмена", я хотел проигнорировать их новый выбор в ComboBox и сохранить старый выбор. Это работало как чемпион!

Для тех, кто пугает момент, когда они видят ссылки на Blend и System.Windows.Interactivity, вам не нужно устанавливать Microsoft Expression Blend. Вы можете загрузить Blend SDK для .NET 4 (или Silverlight).

Blend SDK для .NET 4

Blend SDK для Silverlight 4

О да, в моем XAML я фактически использую это как мое объявление пространства имен для Blend в этом примере:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Ответ 8

Я сделал это так же, как у того, что имеет вышеприведенный splinteror.

Ваше мнение:

<ComboBox  
ItemsSource="{Binding CompetitorBrands}" 
DisplayMemberPath="Value" 
SelectedValuePath="Key" 
SelectedValue="{Binding Path=CompMfgBrandID, 
Mode=TwoWay,
UpdateSourceTrigger=Explicit}" //to indicate that you will call UpdateSource() manually to get the property "CompMfgBrandID" udpated 
SelectionChanged="ComboBox_SelectionChanged"  //To fire the event from the code behind the view
Text="{Binding CompMFGText}"/>

Ниже приведен код обработчика событий "ComboBox_SelectionChanged" из файла кода за представлением. Например, если вы видите myview.xaml, имя файла кода для этого обработчика событий должно быть myview.xaml.cs

private int previousSelection = 0; //Give it a default selection value

private bool promptUser true; //to be replaced with your own property which will indicates whether you want to show the messagebox or not.

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox comboBox = (ComboBox) sender;
            BindingExpression be = comboBox.GetBindingExpression(ComboBox.SelectedValueProperty);

            if (comboBox.SelectedValue != null && comboBox.SelectedIndex != previousSelection)
            {
                if (promptUser) //if you want to show the messagebox..
                {
                    string msg = "Click Yes to leave previous selection, click No to stay with your selection.";
                    if (MessageBox.Show(msg, "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes) //User want to go with the newest selection
                    {

                        be.UpdateSource(); //Update the property,so your ViewModel will continue to do something
                        previousSelection = (int)comboBox.SelectedIndex;  
                    }
                    else //User have clicked No to cancel the selection
                    {
                        comboBox.SelectedIndex = previousSelection; //roll back the combobox selection to previous one
                    }
                }
                else //if don't want to show the messagebox, then you just have to update the property as normal.
                {
                    be.UpdateSource();
                    previousSelection = (int)comboBox.SelectedIndex;
                }
            }
        }

Ответ 9

Вот общий поток, который я использую (не требует каких-либо модификаций или модификаций XAML):

  • Я просто позволяю изменения проходить через ViewModel и отслеживать все, что было ранее. (Если ваша бизнес-логика требует, чтобы выбранный элемент не находился в недопустимом состоянии, я предлагаю переместить его на сторону модели). Этот подход также дружелюбен к ListBoxes, которые отображаются с помощью кнопок Radio Buttons, так как выключение Setter SelectedItem как можно скорее не будет препятствовать подсвечиванию переключателей при появлении окна сообщения.
  • Я сразу вызываю событие OnPropertyChanged независимо от переданного значения.
  • Я помещаю любую отменную логику в обработчик и вызываю, используя SynchronizationContext.Post() (BTW: SynchronizationContext.Post также работает для приложений Windows Store. Поэтому, если у вас есть общий код ViewModel, этот подход все равно будет работать).

    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public List<string> Items { get; set; }
    
        private string _selectedItem;
        private string _previouslySelectedItem;
        public string SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                _previouslySelectedItem = _selectedItem;
                _selectedItem = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
                }
                SynchronizationContext.Current.Post(selectionChanged, null);
            }
        }
    
        private void selectionChanged(object state)
        {
            if (SelectedItem != Items[0])
            {
                MessageBox.Show("Cannot select that");
                SelectedItem = Items[0];
            }
        }
    
        public ViewModel()
        {
            Items = new List<string>();
            for (int i = 0; i < 10; ++i)
            {
                Items.Add(string.Format("Item {0}", i));
            }
        }
    }
    

Ответ 10

Я думаю, проблема в том, что ComboBox устанавливает выбранный элемент в результате действия пользователя после установки значения свойства привязки. Таким образом, элемент Combobox изменяется независимо от того, что вы делаете в ViewModel. Я нашел другой подход, когда вам не нужно сгибать шаблон MVVM. Вот мой пример (извините, что он скопирован из моего проекта и точно не соответствует приведенным выше примерам):

public ObservableCollection<StyleModelBase> Styles { get; }

public StyleModelBase SelectedStyle {
  get { return selectedStyle; }
  set {
    if (value is CustomStyleModel) {
      var buffer = SelectedStyle;
      var items = Styles.ToList();
      if (openFileDialog.ShowDialog() == true) {
        value.FileName = openFileDialog.FileName;
      }
      else {
        Styles.Clear();
        items.ForEach(x => Styles.Add(x));
        SelectedStyle = buffer;
        return;
      }
    }
    selectedStyle = value;
    OnPropertyChanged(() => SelectedStyle);
  }
}

Разница в том, что я полностью очищаю коллекцию предметов, а затем заполняю ее ранее сохраненными элементами. Это заставляет Combobox обновляться, поскольку я использую общий класс ObservableCollection. Затем я вернул выбранный элемент к выбранному элементу, который был установлен ранее. Это не рекомендуется для большого количества предметов, потому что очистка и заполнение списков со списком является дорогостоящим.

Ответ 11

Я хотел бы завершить ответ splintor, потому что наткнулся на проблему с задержкой инициализации в OnSelectedItemChanged:

Когда функция OnSelectedItemChanged возникает до назначения AssociatedObject, использование System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke может иметь нежелательные побочные эффекты, такие как попытка инициализировать newValue со значением по умолчанию для выбора combobox.

Таким образом, даже если ваш ViewModel обновлен, поведение вызовет изменение из текущего значения ViewModel SelectedItem в значение по умолчанию для ComboBox, хранящегося в e.NewValue. Если ваш код вызывает диалоговое окно, пользователь будет предупрежден об изменении, хотя его нет. Я не могу объяснить, почему это происходит, возможно, проблема времени.

Здесь мое исправление

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Interactivity;

namespace MyApp
{
    internal class CancellableSelectionBehaviour : Behavior<Selector>
    {
        protected override void OnAttached()
        {
            base.OnAttached();

            if (MustPerfomInitialChange)
            {
                OnSelectedItemChanged(this, InitialChangeEvent);
                MustPerfomInitialChange = false;
            }

            AssociatedObject.SelectionChanged += OnSelectionChanged;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.SelectionChanged -= OnSelectionChanged;
        }

        public static readonly DependencyProperty SelectedItemProperty =
            DependencyProperty.Register("SelectedItem", typeof(object), typeof(CancellableSelectionBehaviour),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemChanged));

        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }

        public static readonly DependencyProperty IgnoreNullSelectionProperty =
            DependencyProperty.Register("IgnoreNullSelection", typeof(bool), typeof(CancellableSelectionBehaviour), new PropertyMetadata(true));

        /// <summary>
        /// Determines whether null selection (which usually occurs since the combobox is rebuilt or its list is refreshed) should be ignored.
        /// True by default.
        /// </summary>
        public bool IgnoreNullSelection
        {
            get { return (bool)GetValue(IgnoreNullSelectionProperty); }
            set { SetValue(IgnoreNullSelectionProperty, value); }
        }

        /// <summary>
        /// OnSelectedItemChanged can be raised before AssociatedObject is assigned so we must delay the initial change. 
        /// Using System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke has unwanted side effects.
        /// So we use this bool to know if OnSelectedItemChanged must be called afterwards, in OnAttached
        /// </summary>
        private bool MustPerfomInitialChange { get; set; }

        /// <summary>
        /// OnSelectedItemChanged can be raised before AssociatedObject is assigned so we must delay the initial change. 
        /// Using System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke has unwanted side effects.
        /// So we use this DependencyPropertyChangedEventArgs to save the argument needed to call OnSelectedItemChanged.
        /// </summary>
        private DependencyPropertyChangedEventArgs InitialChangeEvent { get; set; }

        /// <summary>
        /// Called when the SelectedItem dependency property is changed.
        /// Updates the associated selector SelectedItem with the new value.
        /// </summary>
        private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (CancellableSelectionBehaviour)d;

            // OnSelectedItemChanged can be raised before AssociatedObject is assigned so we must delay the initial change.
            if (behavior.AssociatedObject == null)
            {
                behavior.InitialChangeEvent = e;
                behavior.MustPerfomInitialChange = true;               
            }
            else
            {
                var selector = behavior.AssociatedObject;
                selector.SelectedValue = e.NewValue;               
            }
        }

        /// <summary>
        /// Called when the associated selector selection is changed.
        /// Tries to assign it to the <see cref="SelectedItem"/> property.
        /// If it fails, updates the selector with  <see cref="SelectedItem"/> property current value.
        /// </summary>
        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (IgnoreNullSelection && (e.AddedItems == null || e.AddedItems.Count == 0)) return;
            SelectedItem = AssociatedObject.SelectedItem;
            if (SelectedItem != AssociatedObject.SelectedItem)
            {
                AssociatedObject.SelectedItem = SelectedItem;
            }
        }
    }
}

Ответ 12

--Xaml

 <ComboBox SelectedItem="{Binding SelectedItem, Mode=TwoWay, Delay=10}" ItemsSource="{Binding Items}"  />

--ViewModel

private object _SelectedItem;
public object SelectedItem 
{
    get { return _SelectedItem;}
    set {
           if(_SelectedItem == value)// avoid rechecking cause prompt msg
            { 
               return;
            } 
            MessageBoxResult result = MessageBox.Show
                    ("Continue change?", MessageBoxButton.YesNo);
            if (result == MessageBoxResult.No)
            {
                ComboBox combo = (ComboBox)sender;
                handleSelection = false;
                combo.SelectedItem = e.RemovedItems[0];
                return;
            }
            _SelectedItem = value;
            RaisePropertyChanged(); 
        }
}