从View To ViewModel发送值

时间:2011-10-15 07:02:32

标签: wpf mvvm viewmodel dependency-properties

我在这里有一个Senario ...(非常抱歉写了这么长的帖子)

我有TreeView(绑定到可观察的电话集合(不同类型))我有一个contentCOntrol,其COntent Binding设置为TreeView的selectedItem

代码......

 <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中选择一个Phone(从contentcontrol填充一个特定的View)时,我希望将UniqueId(PhoneBase具有该属性)传递给我的ViewModel of View,并在viewModel中触发一个函数,以便它可以获得来自BusinessLayer的数据...并初始化ViewModel及其所有属性。

UserControl的CodeBehind

region class - 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的Mediator V2)及其制作应用如果使用15-20分钟左右非常慢

典型视图的ViewModel ..

region class - 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 :(得分:0)

为什么不让您的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; }

您的视图看起来就像这样:

<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事件中执行此操作。

作为旁注,我忘记了你是否可以绑定TreeView的SelectedItem,但如果没有,你可以使用一个看起来像TreeView的ListBox,或者在过去我添加了IsSelected属性到我的TreeView数据对象,并将TreeViewItem.IsSelected属性绑定到该。