我有一個單獨的細節的樹狀視圖通過PRISM庫注射時,我對我的樹型視圖的一個點擊(我可以更新我的項目的所有屬性它)。我的所有物品都有啓用屬性。
問題:
- 當我更新我的編程產權的ViewModels,我的對象被更新。如果我點擊其他treeviewitem並返回到第一個,我會看到該屬性已更新。
- 當我啓用/禁用使用我的詳細信息視圖的項目(前景變灰,屬性發生變化)時,所有更新都很好
- 但在我的情況下,當我嘗試通過由一個contextMenu它不會觸發視圖和所有更新...但我的viewmodel屬性更新...
我該怎麼去錯了?
我在我的treeview中使用ObservableCollection,也許我需要更改我的集合的類型?
我有我的BaseViewModel誰實現NotifyPropertyChanged
public abstract class NotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(Expression<Func<object>> propertyExpression)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(GetPropertyName(propertyExpression)));
}
private string GetPropertyName(Expression<Func<object>> propertyExpression)
{
var unaryExpression = propertyExpression.Body as UnaryExpression;
var memberExpression = unaryExpression == null ? (MemberExpression)propertyExpression.Body : (MemberExpression)unaryExpression.Operand;
var propertyName = memberExpression.Member.Name;
return propertyName;
}
}
因此,我調用屬性變化的方法,但爲什麼我的看法是沒有,那麼更新?
[DefaultValue(true)]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool Enabled
{
get
{
return Model.Enabled;
}
set
{
if (value != Model.Enabled)
{
Model.Enabled = value;
OnPropertyChanged(() => Model.Enabled);
}
}
}
這是我的看法的代碼(命令)
<MenuItem Header="Enable/Disable this equipment" Command="{Binding PlacementTarget.Tag.DataContext.ToogleEquipmentCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"
CommandParameter="{Binding}" InputGestureText="CTRL+D"/>
這裏是我認爲的代碼(分層數據模板從我的樹視圖)
<!-- ModuleItems > IP/Name -->
<HierarchicalDataTemplate DataType="{x:Type siemens:ModuleItemSiemensViewModel}" >
<StackPanel Orientation="Horizontal">
<TextBlock Name="ItemIp"
Text="{Binding Path=Ip}" ContextMenu="{StaticResource ContextMenuEquipment}" Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding Enabled}" Value="True">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Text="/" ContextMenu="{StaticResource ContextMenuEquipment}" Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter Property="Background" Value="LightGray"/>
</DataTrigger>
<DataTrigger Binding="{Binding Enabled}" Value="True">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Name="ItemName" ContextMenu="{StaticResource ContextMenuEquipment}" Tag="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"
Text="{Binding Path=Name}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Enabled}" Value="False">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
<DataTrigger Binding="{Binding Enabled}" Value="True">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
編輯:
這是我的viewmodel和模型: 我真正的問題是當我更新一個項目(與我的屬性啓用)它更新項目,但我的列表(ModuleItems)沒有更新,我需要做什麼來正確實現MVVM,並使我的領域自動更新?
public class ModuleParamSiemensViewModel : ModuleParamBaseViewModel
{
#region Attributes
private ObservableCollection<ModuleItemSiemensViewModel> _moduleItems;
private ModuleParamSiemens _model;
private string _moduleType;
#endregion
#region Constructor
public ModuleParamSiemensViewModel(ModuleParamSiemens moduleParam) : base(moduleParam)
{
this.Model = moduleParam;
this.ModuleType = "Siemens";
ModuleItems = new ObservableCollection<ModuleItemSiemensViewModel>();
Initialize();
}
#endregion
#region Properties
public new ModuleParamSiemens Model
{
get
{
return _model;
}
set
{
if (value != _model)
{
_model = value;
OnPropertyChanged(() => Model);
}
}
}
public new ObservableCollection<ModuleItemSiemensViewModel> ModuleItems
{
get
{
return _moduleItems;
}
set
{
this._moduleItems = value;
OnPropertyChanged(() => ModuleItems);
}
}
public override string ModuleType
{
get
{
return _moduleType;
}
set
{
this._moduleType = value;
OnPropertyChanged(() => ModuleType);
}
}
#endregion
#region Public Methods
public void Initialize()
{
foreach (ModuleItemSiemens item in this.Model.ModuleItems)
{
Add(new ModuleItemSiemensViewModel(item));
}
}
public void Add(ModuleItemSiemensViewModel item)
{
ModuleItems.Add(item);
}
#endregion
}
型號:
public class ModuleParamSiemens : ModuleParam
{
public new ObservableCollection<ModuleItemSiemens> ModuleItems { get; set; }
public ModuleParamSiemens()
{
ModuleItems = new ObservableCollection<ModuleItemSiemens>();
}
}
編輯2:
添加ItemSiemensViewModel
public class ItemSiemensViewModel : ItemBaseViewModel
{
#region Attributes
private ItemSiemens _model;
#endregion
#region Constructor
public ItemSiemensViewModel(ItemSiemens item)
{
this.Model = item;
}
#endregion
#region Properties
public new ItemSiemens Model
{
get
{
return _model;
}
set
{
if (value != _model)
{
_model = value;
OnPropertyChanged(() => Model);
}
}
}
public new OPCInfo Opc
{
get
{
return Model.Opc;
}
set
{
if (value != Model.Opc)
{
Model.Opc = value;
OnPropertyChanged(() => Model.Opc);
}
}
}
public ProtocolInfoSiemens Protocol
{
get
{
return Model.Protocol;
}
set
{
if (value != Model.Protocol)
{
Model.Protocol = value;
OnPropertyChanged(() => Model.Protocol);
}
}
}
#endregion
#region Public Methods
#endregion
}
ItemSiemens:
public class ItemSiemens : Item
{
public ProtocolInfoSiemens Protocol { get; set; }
}
ItemBaseViewModel
public abstract class ItemBaseViewModel : BaseViewModel
{
public OPCInfoBaseViewModel Opc { get; set; }
public ItemBaseViewModel()
{
}
}
項目
public abstract class Item
{
public OPCInfo Opc { get; set; }
}
沒有一個好的[mcve]可以可靠地重現問題,所以不可能知道所有可能的錯誤。也就是說,使用'Expression'來獲取屬性名稱是毫無意義的。你應該使用'nameof'運算符或([IMHO好得多]'[CallerMemberName]'屬性來獲取被更新的屬性的名稱。不是說這裏有任何跡象表明這會改變你的問題,但你應該修正它(也許它會解決你的問題)。 –