2012-03-20 78 views
0

后的价值我有一个包含一个组合框一个WPF用户控件:选定的项目是不会改变的Web服务更新

<UserControl 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="Hartville.SalesScriptApplication.Views.SalesScriptEditorGroups" 
      mc:Ignorable="d" 
     xmlns:events="http://schemas.microsoft.com/expression/2010/interactivity" 
     xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4" 
      xmlns:hartvm="clr-namespace:Hartville.SalesScript.ViewModels;assembly=Hartville.SalesScript.ViewModels" 
      d:DesignHeight="106" d:DesignWidth="909" Background="#FFF3EDED"> 
    <UserControl.Resources> 
     <ResourceDictionary> 
      <hartvm:ViewLocator x:Key="HartvilleLocator" d:IsDataSource="True" /> 
     </ResourceDictionary> 
    </UserControl.Resources> 
    <UserControl.DataContext> 
     <Binding Source="{StaticResource HartvilleLocator}" Path="ScriptEditorGroups" /> 
    </UserControl.DataContext> 
    <Border> 
     <Grid Margin="5,10,0,20"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="Auto"/> 
      </Grid.ColumnDefinitions> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="Auto"/> 
       <RowDefinition Height="Auto"/> 
      </Grid.RowDefinitions> 
      <StackPanel Orientation="Horizontal" Margin="0,10,0,20"> 
       <TextBlock TextWrapping="Wrap" Text="Selected Script Group:"/> 
       <ComboBox Width="250" Margin="10,0,0,0" HorizontalAlignment="Left" ItemsSource="{Binding ScriptGroups}" SelectedItem="{Binding SelectedScriptGroup}" 
        DisplayMemberPath="Name" > 
        <events:Interaction.Triggers> 
         <events:EventTrigger EventName="SelectionChanged"> 
          <cmd:EventToCommand Command="{Binding ScriptGroupSelectedCommand}" PassEventArgsToCommand="False" /> 
         </events:EventTrigger> 
        </events:Interaction.Triggers>    
       </ComboBox> 
      </StackPanel> 
    </Border> 
</UserControl> 

注意:我们正在使用MVVM光框架。您看到的视图定位器只是一个实例化视图模型的类,您将在数据上下文部分中看到该视图模型。

当从组合框中选择某些内容并点击编辑按钮时,用户可以更新名称并保存。但是,当用户单击保存时,您可以在组合框中看到更改的选择,但所选项目仍包含原始名称。因此,例如,我从组合框中选择选项“Hello World”。我将名称更改为“FOOBAR”并单击保存。我更新了代码中的选定项目(我可以看到该属性正在改变)。当我检查组合框时,我看到“FOOBAR”,但所选值仍然显示“Hello World”。此外,“Hello World”的不再是组合框(显然存在,因为我刚刚更新了它

下面是视图模型的代码:?

using System.Windows.Input; 
using System.Collections.ObjectModel; 
using GalaSoft.MvvmLight.Command; 
using Hartville.Common.Controls.ViewModels; 
using Hartville.Common.Controls.ViewModels.Validation; 
using Hartville.SalesScript.ViewModels.Messages; 
using Hartville.Values.Sales; 
using System.Linq; 

namespace Hartville.SalesScript.ViewModels.Scripts 
{ 
    public class ScriptEditorGroups: CommonViewModelBase 
    { 
     private ObservableCollection<ScriptHeader> _scriptGroups; 
     private ObservableCollection<Script> _scripts; 
     private ScriptHeader _selectedScriptGroup; 
     private Script _selectedScript; 
     private bool _isScriptGroupActive; 
     private string _groupName; 
     private bool _shouldEnableScriptGroup; 
     private bool _shouldShowGroupEditPanel; 
     private bool _shouldUseDefaultScript; 
     private bool _shouldShowScriptSelection; 

     public ICommand EditSelectedCommand { get; set; } 
     public ICommand NewGroupCommand { get; set; } 
     public ICommand SaveCommand { get; set; } 
     public ICommand ScriptGroupSelectedCommand { get; set; } 

     public ObservableCollection<ScriptHeader> ScriptGroups 
     { 
      get { return _scriptGroups; } 
      set { SetPropertyValue(ref _scriptGroups, value); } 
     } 

     public ObservableCollection<Script> Scripts 
     { 
      get { return _scripts; } 
      set { SetPropertyValue(ref _scripts, value); } 
     } 

     public ScriptHeader SelectedScriptGroup 
     { 
      get { return _selectedScriptGroup; } 
      set { SetPropertyValue(ref _selectedScriptGroup, value); } 
     } 

     public Script SelectedScript 
     { 
      get { return _selectedScript; } 
      set { SetPropertyValue(ref _selectedScript, value); } 
     } 

     public bool IsScriptGroupActive 
     { 
      get { return _isScriptGroupActive; } 
      set { SetStructPropertyValue(ref _isScriptGroupActive, value); } 
     } 

     public string GroupName 
     { 
      get { return _groupName; } 
      set { SetStructPropertyValue(ref _groupName, value); } 
     } 

     public bool ShouldEnableScriptGroup 
     { 
      get { return _shouldEnableScriptGroup; } 
      set { SetStructPropertyValue(ref _shouldEnableScriptGroup, value); } 
     } 

     public bool ShouldShowGroupEditPanel 
     { 
      get { return _shouldShowGroupEditPanel; } 
      set { SetStructPropertyValue(ref _shouldShowGroupEditPanel, value); } 
     } 

     public bool ShouldUseDefaultScript 
     { 
      get { return _shouldUseDefaultScript; } 
      set { SetStructPropertyValue(ref _shouldUseDefaultScript, value); } 
     } 

     public bool ShouldShowScriptSelection 
     { 
      get { return _shouldShowScriptSelection; } 
      set { SetStructPropertyValue(ref _shouldShowScriptSelection, value); } 
     } 

     public bool IsEdit { get; set; } 
     public bool IsNew { get; set; } 

     protected override void RegisterForMessages() 
     { 
      MessengerService.Register<BeginSalesScriptEditorMessage>(OnBeginSalesScriptEditor); 

      EditSelectedCommand = new RelayCommand(OnEdit); 
      NewGroupCommand = new RelayCommand(OnNewGroup); 
      SaveCommand = new RelayCommand(OnSave); 
      ScriptGroupSelectedCommand = new RelayCommand(OnScriptGroupSelected); 
     } 

     private void OnBeginSalesScriptEditor(BeginSalesScriptEditorMessage message) 
     { 
      ScriptGroups = new ObservableCollection<ScriptHeader>(SalesService.GetAllScriptHeader()); 
      Scripts = new ObservableCollection<Script>(SalesScriptCache.Scripts); 

      ShouldEnableScriptGroup = false; 
      ShouldShowGroupEditPanel = false; 
      ShouldShowScriptSelection = false; 
      IsEdit = false; 
      IsNew = false; 
     } 

     private void OnEdit() 
     { 
      if(SelectedScriptGroup == null) return; 

      IsEdit = true; 
      ShouldShowGroupEditPanel = true; 
      ShouldShowScriptSelection = true; 
      GroupName = SelectedScriptGroup.Name; 
      SelectedScript = SalesScriptCache.Scripts.FirstOrDefault(s => s.ScriptId == SelectedScriptGroup.StartScriptId); 
     } 

     private void OnNewGroup() 
     { 
      IsNew = true; 
      GroupName = string.Empty; 
      ShouldShowGroupEditPanel = true; 
      ShouldShowScriptSelection = false; 
     } 

     private void OnSave() 
     { 
      ThreadManagement.ExecuteInSeparateThread(ProcessScriptUpdate); 
     } 

     private void OnScriptGroupSelected() 
     { 
      if(SelectedScriptGroup == null) return; 

      MessengerService.Send(ScriptHeaderSelectedMessage.Create(SelectedScriptGroup)); 
      ShouldEnableScriptGroup = true; 
     } 

     protected override void SetDesignTimeInfo(){} 

     protected void ResetValues() 
     { 
      ShouldEnableScriptGroup = false; 
      ShouldShowGroupEditPanel = false; 
      IsScriptGroupActive = false; 
      IsEdit = false; 
      IsNew = false; 
      ShouldShowScriptSelection = false; 
     } 

     private int CreateNewScriptGroup() 
     { 
      var scriptHeader = new ScriptHeader 
            { 
             Name = GroupName, 
             IsActive = IsScriptGroupActive 
            }; 

      MessengerService.Send(ScriptHeaderSelectedMessage.Create(scriptHeader)); 
      return SalesService.ScriptHeaderInsertUpdate(scriptHeader); 
     } 

     private int EditExistingScriptGroup() 
     { 
      if(SelectedScriptGroup == null) return 0; 

      var scriptHeader = new ScriptHeader 
            { 
             Name = GroupName, 
             IsActive = IsScriptGroupActive, 
             ScriptHeaderId = SelectedScriptGroup.ScriptHeaderId, 
             StartScriptId = SelectedScript.ScriptId 
            }; 

      MessengerService.Send(ScriptHeaderSelectedMessage.Create(scriptHeader)); 
      return SalesService.ScriptHeaderInsertUpdate(scriptHeader); 
     } 

     private void ProcessScriptUpdate() 
     { 
      var returnId = 0; 

      if (IsNew) 
       returnId = CreateNewScriptGroup(); 
      else if (IsEdit) 
       returnId = EditExistingScriptGroup(); 

      ScriptGroups = new ObservableCollection<ScriptHeader>(SalesService.GetAllScriptHeader()); 
      SelectedScriptGroup = ScriptGroups.FirstOrDefault(h => h.ScriptHeaderId == returnId); 

      ResetValues(); 
     } 
    } 
} 

如何解决这个问题

编辑:

这是调用通知SetPropertyValue方法:

public virtual void SetPropertyValue<T>(ref T currentValue, T newValue, Action<T> extraFunction = null, Action voidAfterSetAction = null) where T : class 
     { 
      if (currentValue == newValue) return; 

      currentValue = newValue; 

      PropertyHasChanged(); 

      if (extraFunction != null) extraFunction(newValue); 

      if (voidAfterSetAction != null) voidAfterSetAction(); 
     } 

编辑:

这是整个基类,保存属性变化代码:

using System; 
using System.ComponentModel; 
using System.Diagnostics; 
using GalaSoft.MvvmLight; 
using Hartville.Common.Controls.Messaging; 
using Hartville.Common.Controls.Modules; 
using Hartville.Common.Controls.ViewModels.Validation; 
using Hartville.Common.Controls.WebServices; 
using Hartville.Common.Threading; 

namespace Hartville.Common.Controls.ViewModels 
{ 
    public abstract class CommonViewModelBase : ViewModelBase, IDataErrorInfo 
    { 


     public string this[string columnName] 
     { 
      get 
      { 
       var validationReturn = ValidationManager.Validate(columnName); 

       OnValidationComplete(); 

       return validationReturn; 
      } 
     } 

     public string Error 
     { 
      get { return null; } 
     } 

     protected CommonViewModelBase() 
     { 
      ValidationManager = ValidationManager.Start(this); 

      RegisterForMessages(); 

      if (IsInDesignMode) SetDesignTimeInfo(); 
     } 

     public virtual void Reset() 
     { 
      IsProcessing = false; 
     } 

     public virtual void OnValidationComplete() 
     { 
     } 

     public virtual void SetPropertyValue<T>(ref T currentValue, T newValue, Action<T> extraFunction = null, Action voidAfterSetAction = null) where T : class 
     { 
      if (currentValue == newValue) return; 

      currentValue = newValue; 

      PropertyHasChanged(); 

      if (extraFunction != null) extraFunction(newValue); 

      if (voidAfterSetAction != null) voidAfterSetAction(); 
     } 

     public virtual void SetPropertyValue<T>(ref T currentValue, T newValue, Action extraFunction) where T : class 
     { 
      if (currentValue == newValue) return; 

      currentValue = newValue; 

      PropertyHasChanged(); 

      if (extraFunction != null) extraFunction(); 
     } 

     public virtual void SetStructPropertyValue<T>(ref T currentValue, T newValue, Action<T> extraFunction = null, Action voidActionAfterSetAction = null) 
     { 
      currentValue = newValue; 

      PropertyHasChanged(); 

      if (extraFunction != null) extraFunction(newValue); 

      if (voidActionAfterSetAction != null) voidActionAfterSetAction(); 
     } 

     public virtual void SetStructPropertyValue<T>(ref T currentValue, T newValue, Action extraFunction) 
     { 
      currentValue = newValue; 

      PropertyHasChanged(); 

      if (extraFunction != null) extraFunction(); 
     } 

     public virtual void SetValue<T>(ref T currentValue, T newValue, Action<T> voidOldValueAction = null, Action voidAfterSetAction = null) where T : class 
     { 
      var oldVal = currentValue; 

      if (currentValue == newValue) return; 

      currentValue = newValue; 

      PropertyHasChanged(); 

      if (voidOldValueAction != null) voidOldValueAction(oldVal); 

      if (voidAfterSetAction != null) voidAfterSetAction(); 
     } 

     protected abstract void RegisterForMessages(); 
     protected abstract void SetDesignTimeInfo(); 

     protected void SendModalCloseMessage() 
     { 
      MessengerService.Send(ModalCommandMessage.Create(ModalOptions.Close)); 
     } 

     protected void SendModalOpenMessage(ModalName windowName, Guid? customID = null) 
     { 
      MessengerService.Send(ModalCommandMessage.Create(ModalOptions.Open, windowName, customID)); 
     } 

     private void PropertyHasChanged() 
     { 
      var currentFrame = 2; 

      var frame = new StackFrame(currentFrame); 

      var propertyName = string.Empty; 

      if (frame.GetMethod().Name.Length > 4) propertyName = GetPropertyName(frame); 

      while (!frame.GetMethod().Name.StartsWith("set_")) 
      { 
       currentFrame++; 

       frame = new StackFrame(currentFrame); 

       if (frame.GetMethod().Name.Length > 4) propertyName = GetPropertyName(frame); 
      } 

      RaisePropertyChanged(propertyName); 
     } 

     private static string GetPropertyName(StackFrame frame) 
     { 
      return frame.GetMethod().Name.Substring(4); 
     } 
    } 
} 

回答

0

您需要执行INotifyPropertyChanged并调用的PropertyChanged在

public ScriptHeader SelectedScriptGroup 
    { 
     set { SetPropertyValue(ref _selectedScriptGroup, value); } 
    } 
0

添加到什么布拉姆有已经提到过,您必须在CommonViewModelBase或当前视图模型中实现INotifyPropertyChanged接口。你应该调用所有属性设置器的PropertyChanged方法,这些属性设置器的值在Datacontext被分配给视图后将改变。

public ScriptHeader ScriptGroups 
{ 
    set { SetPropertyValue(ref _selectedScriptGroup, value); 
      PropertyChanged("SelectedScriptGroup "); 
     } 
} 

public ScriptHeader SelectedScriptGroup 
{ 
    set { SetPropertyValue(ref _selectedScriptGroup, value); 
      PropertyChanged("SelectedScriptGroup"); 
     } 
} 

否则,您的View无法知道控件所绑定的属性值已更改。对于实现,请参考Property Changed Implementation

+0

对不起,我可能应该提到,如果你看看视图模型,这些属性会照顾set(SetPrpertyValue)中的INotify实现。 – ErisOfDevDischord 2012-03-21 12:48:03

+0

我不确定如果这个** PropertyHasChanged **方法是通知如果当前属性已经改变,因为我没有看到你传递属性名称的任何地方。它如何通知哪些财产已经改变? – 2012-03-21 14:32:50

+0

我添加了整个视图模型库(这是属性更改代码的存在位置) – ErisOfDevDischord 2012-03-21 14:41:49