I have a senario here... (Extremely sorry writing such a long post)
I have are TreeView(Bound to the observable collection of Phones(Different types)) i have a contentCOntrol whose COntent Binding is set to the selectedItem for TreeView
Code....
<Border Grid.Column="2">
<ContentC开发者_StackOverflow中文版ontrol 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>
Problem is that when i select a Phone from TreeView(a specific View is populated from contentcontrol) I wish to pass UniqueId(PhoneBase has that Property) to my ViewModel of View and also fire a function in viewModel so that it can get Data from BusinessLayer... and Initialize the ViewModel and all its Properties.
CodeBehind for UserControl
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
Also in ViewModel I have Messenger Registrations .... but Every time i selected another phone type and then select the former type the messenger are registered again without deregistering Earlier... (I dont have any Deregister method in Messenger, using Marlon's Mediator V2) and its making application Very Slow if used for an 15-20 min or so
ViewModel for a Typical View..
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
I am absolutly Puzzled what to do... ANy help in this regrad would be GR8!!! Thanks
Why not have your ParentViewModel track the SelectedItem instead of having your View do it? I personally hate doing any kind of business logic in my View. It should just be a pretty layer that sits on top of my ViewModels to make it easier for the user to interact with them.
For example, your PhonesViewModel might have:
// Leaving out get/set method details for simplicity
Observable<QuertyPhone> Phones { get; set; }
QuertyPhone SelectedPhone { get; set; }
ICommand SaveSelectedPhoneCommand { get; }
ICommand CancelSelectedPhoneCommand { get; }
Your View would simply look something like this:
<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>
I would leave the validation in your QuertyPhone
model, but would move the data access to the ViewModel. In my opinion, your models should just be dumb data objects. You also only have to register for messaging in a single place (your ViewModel), and if you need to do anything when the SelectedPhone changes, simply do it in the PropertyChanged event.
As a side note, I forget if you can bind a TreeView's SelectedItem or not, but if not you can either use a ListBox styled to look like a TreeView, or in the past I've added IsSelected
properties to my TreeView data objects, and bound the TreeViewItem.IsSelected
property to that.
精彩评论