我试着了解mvvm。 我想从我的电脑上读取制造商,这就是目标。
问题: - xaml中的标签为空
我的理解:
我希望有人能帮助我理解mvvm模式。
我的xaml:
<Window x:Class="MVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:get="clr-namespace:MVVM"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl Name="tabControl1">
<TabItem Header="Uebersicht" Name="tabUeberischt">
<TabItem.Resources>
<ObjectDataProvider x:Key="OverviewData" ObjectType="{x:Type get:VM_lalala}" MethodName="GetDataFromRep" />
</TabItem.Resources>
<DockPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="26" />
<RowDefinition Height="26" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="Hersteller: " Grid.Row="0" Grid.Column="0"/>
<Label Content="{Binding Path=Hersteller, Source={StaticResource OverviewData}}" Grid.Row="0" Grid.Column="1"/>
</Grid>
</DockPanel>
</TabItem>
</TabControl>
</Grid>
</Window>
这里是我的c#代码:
namespace MVVM
{
class VM_lalala : VM_Base
{
private string _Hersteller;
private UebersichtRepository _Rep;
public string Hersteller
{
get { return this._Hersteller; }
set
{
if (this._Hersteller != value)
{
this._Hersteller = value;
this.NotifyPropertyChanged("Hersteller");
}
}
}
public void GetDataFromRep()
{
_Rep.GetInfo(this);
}
public VM_lalala()
{
this._Rep = new UebersichtRepository();
}
}
class UebersichtRepository : VM_Base
{
private static VM_lalala _ViewModel;
public bool GetInfo(VM_lalala Aktu_ViewModel)
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_ComputerSystem");
foreach (ManagementObject queryObj in searcher.Get())
{
_ViewModel.Hersteller = queryObj["Manufacturer"].ToString();
}
return true;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return false;
throw;
}
}
}
class VM_Base : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
}
编辑: 在Steve B的例子中我重构了我的代码:
现在它起作用了。 问题是,用他自己的方法(GetDataFromRep)填充Viewmodel是不对的。
工作流程现在是:
是mvvm思维和模式的工作流程投诉吗?
新的c#代码:
public class UebersichtWerte : VM_Base
{
public string Hersteller;
public string Model;
}
public class ViewModelUebersicht : VM_Base
{
private string _Hersteller;
private string _Modell;
private UebersichtRepository _Rep;
public string Hersteller
{
get { return this._Hersteller; }
set
{
if (this._Hersteller != value)
{
this._Hersteller = value;
this.NotifyPropertyChanged("Hersteller");
}
}
}
public string Modell
{
get { return this._Modell; }
set
{
if (this._Modell != value)
{
this._Modell = value;
}
}
}
public void GetDataFromRep()
{
UebersichtWerte _PCDATA = new UebersichtWerte();
_PCDATA = _Rep.GetInfo();
this.Hersteller = _PCDATA.Hersteller;
this.Modell = _PCDATA.Model;
}
public ViewModelUebersicht()
{
this._Rep = new UebersichtRepository();
GetDataFromRep();
}
}
class UebersichtRepository
{
public UebersichtWerte GetInfo()
{
try
{
UebersichtWerte _DATA = new UebersichtWerte();
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_ComputerSystem");
foreach (ManagementObject queryObj in searcher.Get())
{
_DATA.Hersteller = queryObj["Manufacturer"].ToString();
_DATA.Model = queryObj["Model"].ToString();
}
return _DATA;
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
return null;
throw;
}
}
}
和新的XAML代码:
<Window x:Class="MVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:VM="clr-namespace:MVVM"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TabControl Name="tabControl1">
<TabItem Header="Uebersicht" Name="tabUeberischt">
<TabItem.Resources>
<VM:ViewModelUebersicht x:Key="VM_Uebersicht" />
</TabItem.Resources>
<DockPanel>
<Grid DataContext="{StaticResource VM_Uebersicht}">
<Grid.RowDefinitions>
<RowDefinition Height="26" />
<RowDefinition Height="26" />
<RowDefinition Height="26" />
<RowDefinition Height="26" />
<RowDefinition Height="26" />
<RowDefinition Height="26" />
<RowDefinition Height="26"/>
<RowDefinition Height="26"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Content="Hersteller: " Grid.Row="0" Grid.Column="0"/>
<Label Content="{Binding Hersteller, UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Grid.Column="1"/>
<Label Content="Modell: " Grid.Row="1" Grid.Column="0"/>
<Label Content="{Binding Modell, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1" Grid.Column="1"/>
</Grid>
</DockPanel>
</TabItem>
</TabControl>
</Grid>
</Window>
答案 0 :(得分:1)
几个步骤:
首先,我建议您重构代码以避免层之间的依赖。具体而言,更改您的存储库类以避免它依赖于VM:
public class UebersichtRepository
{
public string GetInfo()
{
string result = null;
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_ComputerSystem");
foreach (ManagementObject queryObj in searcher.Get())
{
result = queryObj["Manufacturer"].ToString();
}
return result;
}
}
然后,在您的调用代码中,只需:
public void GetDataFromRep()
{
this.Hersteller = _Rep.GetInfo();
}
其次,为了触发数据检索,您只需调用GetDataFromRep
即可最后,您必须正确设置绑定。可能的方法是将datacontext直接定义到VM的实例:
<Window.Resources>
<vm:VM_lalala x:Key="lalala" />
</Window.Resources>
然后,只需绑定您的标签:
<Label Content="{Binding Hersteller}" Grid.Row="0" Grid.Column="1"/>
答案 1 :(得分:0)
您可以使用Window
资源来指定静态资源,这将代表您的ViewModel
:
<Window.Resources>
<vm:VM_lalala x:Key="viewmodel" />
</Window.Resources>
然后,您可以将其用作网格的DataContext
。
<Grid DataContext="{StaticResource viewmodel}">
然后你可以写
<Label Content="{Binding Hersteller}" Grid.Row="0" Grid.Column="1"/>
另外,请使用public class
而不是class
。
答案 2 :(得分:0)
将资源定义为外部网格的资源并修改网格的定义:
<Grid DataContext="{Binding Source={StaticResource OverviewData}}" >
否则绑定没有他们可以使用的上下文。
答案 3 :(得分:0)
关于MVVM部分的一些评论:
您的UebersichtRepository将是Model-View-ViewModel的“模型”部分。因此它不应该从VM_Base派生 - 它甚至不使用可能改变的Properties。
此外,模型不应该依赖于ViewModel。我想知道为什么代码运行没有Nullpointer Exception,因为你将Aktu_ViewModel作为参数传递,但稍后设置_ViewModel.Hersteller - 并且_ViewModel本身永远不会被设置。但无论如何,你应该完全删除Aktu_ViewModel和_ViewModel,而不是返回信息而不是bool。由于您使用Exceptions进行错误处理,因此bool特别无用。
谁调用了GetDataFromRep方法?