Отправка значений из View To ViewModel - PullRequest
0 голосов
/ 15 октября 2011

У меня есть сенарио здесь ... (Крайне жаль писать такой длинный пост)

У меня есть TreeView (привязан к наблюдаемой коллекции телефонов (разных типов)), у меня есть contentCOntrol, для которого для привязки контента установлено значение selectedItem для TreeView

Код ....

 <Border Grid.Column="2">
            <ContentControl Name="userControlContentControl"
                            Content="{Binding ElementName=PhoneTreeViewUserControl,
                                              Path=SelectedItem,
                                              Converter={StaticResource ResourceKey=rightDisplayConverter}}">
                <ContentControl.Resources>
                    <DataTemplate DataType="{x:Type EntityLayer:Settings}">
                        <ViewLayer:SettingsView />
                    </DataTemplate>                       
                    <DataTemplate DataType="{x:Type EntityLayer:CandyBarPhones}">
                        <ViewLayer:CandyBarPhonesListView />
                    </DataTemplate>                        
                    <DataTemplate DataType="{x:Type EntityLayer:CandyBarPhone}">
                        <ViewLayer:CandyBarPhoneView />
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type EntityLayer:QwertyPhones}">
                        <ViewLayer:QwertyPhonesListView />
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type EntityLayer:QuertyPhone}">
                        <ViewLayer:QuertyPhoneView />
                    </DataTemplate>
                                       </ContentControl.Resources>
            </ContentControl>
        </Border>

Проблема в том, что когда я выбираю Телефон из TreeView (определенный контент заполняется из contentcontrol), я хочу передать UniqueId (PhoneBase имеет это свойство) в мою ViewModel of View, а также запустить функцию в viewModel, чтобы он мог получить Данные из BusinessLayer ... и инициализируйте ViewModel и все его свойства.

CodeBehind для UserControl

региональный класс - QuertyPhoneView

/// <summary>
///   Interaction logic for ProductIdEditorView.xaml
/// </summary>
public partial class QuertyPhoneView : BaseUserControl
{
    QertyPhoneViewModel quertyPhoneViewModel;
    #region Constructor

    /// <summary>
    /// </summary>
    public ProductIdEditorView()
    {
        InitializeComponent();
        quertyPhoneViewModel =
            new quertyPhoneViewModel ();
        this.DataContext = quertyPhoneViewModel;
    }

    # endregion
}

#endregion

Также в ViewModel у меня есть регистрация Messenger .... но каждый раз, когда я выбираю другой тип телефона, а затем выбираю прежний, мессенджер регистрируется снова без отмены регистрации ранее ... (У меня нет метода отмены регистрации в Messenger, используя Marlon's Mediator V2) и его применение, очень медленное, если используется в течение 15-20 минут или около того

ViewModel для типичного вида ..

региональный класс - QuertyPhoneViewModel

/// <summary>
///   QuertyPhoneViewModel
/// </summary>
public class QuertyPhoneViewModel : BaseViewModel
{
    # region Member Variables

    /// <summary>
    ///   quertyPhoneDetails
    /// </summary>
    private QuertyPhone quertyPhoneDetails;

    /// <summary>
    ///   oldQuertyPhoneDetails
    /// </summary>
    private ProductId oldQuertyPhoneDetails;

    /// <summary>
    ///   productIds
    /// </summary>
    private QuertyPhones quertyPhones;

    /// <summary>
    ///   productIdModel
    /// </summary>
    private readonly QuertyPhoneModal quertyPhoneModal;

    /// <summary>
    ///   log
    /// </summary>
    private static readonly ILog log =
        LogManager.GetLogger(typeof (QuertyPhoneViewModel));

    /// <summary>
    ///   selectedCalTblName
    /// </summary>
    private CalibrationTable selectedCalTblName;

    # endregion

    # region Constructor

    /// <summary>
    ///   QuertyPhoneViewModel
    /// </summary>
    public QuertyPhoneViewModel()
    {
        RegisterForMessage();
        quertyPhoneModal= new QuertyPhoneModal();
        if (QuertyPhoneDetails == null)
        {
            //Requesting TreeViewUsersontrol To send Details
           // I wish to remove these registrations
            Messenger.NotifyColleagues<ProductId>(
                MessengerMessages.SEND_SELECTED_PHONE, QuertyPhoneDetails);
        }
        CancelPhoneDetailsChangeCommand = new RelayCommand(CancelQuertyPhoneDetailsChanges,
                                               obj => this.IsDirty);
        SavePhoneDetailsChangeCommand = new RelayCommand(SaveQuertyPhoneDetailsToTree,
                                                CanSaveQuertyPhoneDetailsToTree);
    }

    # endregion

    # region Properties

    /// <summary>
    ///   CalibrationTblNameList
    /// </summary>
    public ObservableCollection<CalibrationTable> CalibrationTblNameList { get; set; }

    /// <summary>
    ///   CancelPhoneDetailsChangeCommand
    /// </summary>
    public ICommand CancelPhoneDetailsChangeCommand { get; set; }

    /// <summary>
    ///   SavePhoneDetailsChangeCommand
    /// </summary>
    public ICommand SavePhoneDetailsChangeCommand { get; set; }

    /// <summary>
    ///   QuertyPhoneDetails
    /// </summary>
    public ProductId QuertyPhoneDetails
    {
        get { return quertyPhoneDetails; }
        set
        {
            quertyPhoneDetails = value;
            OnPropertyChanged("QuertyPhoneDetails");
        }
    }

    /// <summary>
    ///   SelectedCalTblName
    /// </summary>
    public CalibrationTable SelectedCalTblName
    {
        get { return selectedCalTblName; }
        set
        {
            selectedCalTblName = value;
            OnPropertyChanged("SelectedCalTblName");
            if (selectedCalTblName != null)
            {
                QuertyPhoneDetails.CalibrationTableId =
                    selectedCalTblName.UniqueId;
            }
        }
    }

    /// <summary>
    ///   QuertyPhones
    /// </summary>
    public QuertyPhones QuertyPhones
    {
        get { return productIds; }
        set
        {
            productIds = value;
            OnPropertyChanged("QuertyPhones");
        }
    }

    # endregion

    # region Public Methods

    # endregion

    # region Private Methods

    /// <summary>
    ///   RegisterForMessage
    ///  I wish to remove these registrations too
    /// </summary>
    private void RegisterForMessage()
    {
        log.Debug("RegisterForMessage" + BaseModel.FUNCTION_ENTERED_LOG);
        Messenger.Register(MessengerMessages.RECIEVE_SELECTED_PHONE,
                           (Action<ProductId>) (o =>
                                                    {
                                                        if (o != null)
                                                        {
                                                            QuertyPhoneDetails
                                                                =
                                                                o.Clone() as
                                                                ProductId;
                                                            AttachChangeEvents
                                                                ();
                                                            oldQuertyPhoneDetails
                                                                = o;
                                                            SetCalibrationTables
                                                                ();
                                                        }
                                                    }));
        Messenger.Register(MessengerMessages.REFRESH_PHONEDETILAS,
                           (Action<string>)
                           (o =>
                                {
                                    GetOldQuertyPhoneDetails(o);
                                    this.IsDirty = false;
                                }));
        log.Debug("RegisterForMessage" + BaseModel.FUNCTION_EXIT_LOG);
    }

    /// <summary>
    ///   CanSaveQuertyPhoneDetailsToTree
    /// </summary>
    /// <param name = "obj"></param>
    /// <returns></returns>
    private bool CanSaveQuertyPhoneDetailsToTree(object obj)
    {
        return this.IsDirty && ValidateQuertyPhoneDetails();
    }

    /// <summary>
    ///   SaveQuertyPhoneDetailsToTree
    /// </summary>
    /// <param name = "obj"></param>
    private void SaveQuertyPhoneDetailsToTree(object obj)
    {
        log.Debug("SaveQuertyPhoneDetails" + BaseModel.FUNCTION_ENTERED_LOG);
        if (Utility.IsStringNullOrEmpty(QuertyPhoneDetails.CalibrationTableId))
        {
            MessageBoxResult result =
                ShowMessageDialog(
                    "Calibration Table name is not set.Do you wish to proceed?",
                    "Save ProductId",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Exclamation);
            if (result == MessageBoxResult.Yes)
            {
                SaveDetails();
            }
        }
        else
        {
            SaveDetails();
        }
        log.Debug("SaveQuertyPhoneDetails" + BaseModel.FUNCTION_EXIT_LOG);
    }

    /// <summary>
    ///   SaveDetails
    /// </summary>
    private void SaveDetails()
    {
        log.Debug("SaveDetails" + BaseModel.FUNCTION_ENTERED_LOG);
        if (productIdModel.SaveQuertyPhoneDetails(QuertyPhoneDetails))
        {
            UpdateProgressbarStatus(
                "ProductId " + QuertyPhoneDetails.Specs
                + " saved successfully.",
                false);
            this.IsDirty = false;
        }
        else
        {
            ShowMessageDialog(
                "ProductId " + QuertyPhoneDetails.Specs +
                " not saved successfully.",
                "Save ProductId",
                MessageBoxButton.OK,
                MessageBoxImage.Error);
            UpdateProgressbarStatus(
                "ProductId " + QuertyPhoneDetails.Specs
                + " not saved successfully.",
                false);
        }
        log.Debug("SaveDetails" + BaseModel.FUNCTION_EXIT_LOG);
    }

    /// <summary>
    ///   SetCalibrationTables
    /// </summary>
    private void SetCalibrationTables()
    {
        log.Debug("SetCalibrationTables" + BaseModel.FUNCTION_ENTERED_LOG);
        CalibrationTblNameList =
            productIdModel.FileData.CalibrationTables.CalibrationTableList;
        SelectedCalTblName = (CalibrationTblNameList.Where(
            calibrationTable =>
            calibrationTable.UniqueId.Equals(
                QuertyPhoneDetails.CalibrationTableId))).FirstOrDefault();
        log.Debug("SetCalibrationTables" + BaseModel.FUNCTION_EXIT_LOG);
    }

    /// <summary>
    ///   CancelQuertyPhoneDetailsChanges
    /// </summary>
    /// <param name = "obj"></param>
    private void CancelQuertyPhoneDetailsChanges(object obj)
    {
        log.Debug("CancelQuertyPhoneDetailsChanges" + BaseModel.FUNCTION_ENTERED_LOG);
        GetOldQuertyPhoneDetails(QuertyPhoneDetails.Specs);
        this.IsDirty = false;
        productIdModel.SelectMainProductList();
        Messenger.NotifyColleagues<bool>(
            MessengerMessages.POP_UP_CLOSE_REQUEST, true);
        log.Debug("CancelQuertyPhoneDetailsChanges" + BaseModel.FUNCTION_EXIT_LOG);
    }

    /// <summary>
    ///   GetOldQuertyPhoneDetails
    /// </summary>
    /// <param name = "idNumber"></param>
    private void GetOldQuertyPhoneDetails(string idNumber)
    {
        log.Debug("GetOldQuertyPhoneDetails" + BaseModel.FUNCTION_ENTERED_LOG);
        if (!string.IsNullOrEmpty(idNumber))
        {
            ProductId tempQuertyPhoneDetails =
                productIdModel.GetProduct(idNumber).Clone() as ProductId;
            if (tempQuertyPhoneDetails != null)
            {
                QuertyPhoneDetails = tempQuertyPhoneDetails;
                QuertyPhoneDetails.Reset();
            }
            AttachChangeEvents();
        }
        log.Debug("GetOldQuertyPhoneDetails" + BaseModel.FUNCTION_EXIT_LOG);
    }

    /// <summary>
    ///   AttachChangeEvents
    /// </summary>
    private void AttachChangeEvents()
    {
        log.Debug("AttachChangeEvents" + BaseModel.FUNCTION_ENTERED_LOG);
        QuertyPhoneDetails.Reset();
        QuertyPhoneDetails.PropertyChanged -= OnQuertyPhoneDetailsChanged;

        QuertyPhoneDetails.PropertyChanged += OnQuertyPhoneDetailsChanged;

        log.Debug("AttachChangeEvents" + BaseModel.FUNCTION_EXIT_LOG);
    }

    private void OnQuertyPhoneDetailsChanged(object sender,
                                           PropertyChangedEventArgs e)
    {
        if (QuertyPhoneDetails.Changes.Count > 0)
        {
            OnItemDataChanged(sender, e, QuertyPhoneDetails.Changes.Count);
        }
    }

    /// <summary>
    ///   ValidateQuertyPhoneDetails
    /// </summary>
    /// <returns></returns>
    private bool ValidateQuertyPhoneDetails()
    {
        log.Debug("ValidateQuertyPhoneDetails" + BaseModel.FUNCTION_ENTERED_LOG);
        if (
            !Utility.IsValidAlphanumeric(
                QuertyPhoneDetails.ControllerInformation)
            ||
            (!Utility.IsValidAlphanumeric(QuertyPhoneDetails.PhoneId))
            || (!Utility.IsValidAlphanumeric(QuertyPhoneDetails.Specs)))
        {
            QuertyPhoneDetails.ErrorMsg =
                AddTreeNodeViewModel.ERROR_NO_ALPHANUMERIC;
            return false;
        }
        QuertyPhoneDetails.ErrorMsg = string.Empty;
        log.Debug("ValidateQuertyPhoneDetails" + BaseModel.FUNCTION_EXIT_LOG);
        return true;
    }

    # endregion
}

#endregion

Я абсолютно озадачен, что делать ... Любая помощь в этом regrad была бы GR8 !!! Спасибо

1 Ответ

0 голосов
/ 17 октября 2011

Почему бы вашему ParentViewModel не отслеживать SelectedItem вместо того, чтобы ваш View делал это?Я лично ненавижу делать какую-либо бизнес-логику в моем представлении.Это должен быть просто красивый слой, который расположен поверх моих моделей ViewModel, чтобы пользователю было легче взаимодействовать с ними.

Например, ваша модель PhonesViewModel может иметь:

// Leaving out get/set method details for simplicity
Observable<QuertyPhone> Phones { get; set; }
QuertyPhone SelectedPhone { get; set; }

ICommand SaveSelectedPhoneCommand { get; }
ICommand CancelSelectedPhoneCommand { get; }

YourПредставление будет просто выглядеть примерно так:

<DockPanel>
    <TreeView DockPanel.Dock="Left"
              ItemsSource="{Binding Phones}"
              SelectedItem="{Binding SelectedPhone}" />

    <StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
        <Button Content="{Binding SaveCommand}" />
        <Button Content="{Binding CancelCommand}" />
    </StackPanel>

    <ContentControl Content="{Binding SelectedPhone} />
</DockPanel>

Я бы оставил проверку в вашей модели QuertyPhone, но переместил бы доступ к данным в ViewModel.На мой взгляд, ваши модели должны быть просто тупыми объектами данных.Вам также нужно только зарегистрироваться для обмена сообщениями в одном месте (ваша ViewModel), и если вам нужно что-то сделать, когда SelectedPhone изменится, просто сделайте это в событии PropertyChanged.

В качестве примечания, я забылесли вы можете привязать SelectedItem TreeView или нет, но если нет, вы можете использовать ListBox, стилизованный под TreeView, или в прошлом я добавлял IsSelected свойства к моим объектам данных TreeView и ограничивал TreeViewItem.IsSelectedсвойство к этому.

...