我試圖設置一個MVVM風格的應用程序,我想我會讓自己陷入與這些項目的交互的幾個節點,並希望有人可以提供幫助。我在這裏做錯了什麼嗎?如何最好地應用WPF MVVM?
我想我的主要2個問題是
- 我應該如何從我的模型去我的看法。目前我正在嘗試通過轉換器完成此操作。
- 如果使用轉換器是正確的,我該如何正確工作?我相信Node構造函數中設置的datacontext被包含轉換器的XAML所取代。
我的類(簡化比特):
IFieldDescription
節點模型
// Class that is supposed to be the ViewModel
public class NodeModel : NotifyPropertyChanged
{
internal NodeModel() { }
public NodeModel(IFieldDescription fieldDescription)
{
this.FieldDescription = fieldDescription;
}
protected IFieldDescription FieldDescription
{
get { return this.fieldDescription; }
set {
this.fieldDescription = value;
this.OnPropertyChanged("Name");
this.OnPropertyChanged("Disabled");
this.OnPropertyChanged("PrimaryKey"); }
}
private IFieldDescription fieldDescription;
public String Name { get { return this.FieldDescription.Name; } }
public Boolean Disabled { get { return this.FieldDescription.Disabled; } }
}
節點 後面
public Node(NodeModel model)
{
this.DataContext = model;
this.InitializeComponent();
}
代碼XAML
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:GO" x:Class="GO.Node" Background="White"
>
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <!-- Primary Key Icon -->
<ColumnDefinition Width="Auto"/> <!-- Type Icon -->
<ColumnDefinition/> <!-- Node Text -->
<ColumnDefinition Width="Auto"/> <!-- Option Cog -->
<ColumnDefinition Width="Auto"/> <!-- Match Icon -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<local:AttributeDataTypeConverter x:Key="DateTypeConverter"/>
</Grid.Resources>
<Image Grid.Column="0" Source="C:\Users\ian.wright\Documents\Expression\Blend 4\Projects\GO\GO\Resources\Images\PrimaryKey.png" Stretch="None" Visibility="{Binding Path=IsPrimaryKey}"/>
<Image Grid.Column="1" Source="{Binding Path=Type, Converter={StaticResource DateTypeConverter}}" Stretch="None"/>
<TextBlock Grid.Column="2" Text="{Binding Path=Name}" VerticalAlignment="Bottom" Margin="0,0,0,2"/>
<Image Grid.Column="3" Source="C:\Users\ian.wright\Documents\Expression\Blend 4\Projects\GO\GO\Resources\Images\Cog.png" Stretch="None" Visibility="{Binding Path=HasOptions}"/>
<Image Grid.Column="4" Source="{Binding Path=CastType}" Stretch="None"/>
</Grid>
</UserControl>
主窗口
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
x:Class="GO.MainWindow"
xmlns:local="clr-namespace:GO"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid Width="200" Height="500">
<Grid.Resources>
<local:NodeConverter x:Key="NodeConverter"/>
<local:ModelToViewConverter x:Key="ModelConverter"/>
</Grid.Resources>
<!--<ListView Grid.Column="1" ItemsSource="{Binding Path=FieldDescriptions, Converter={StaticResource ModelConverter}}">-->
<ListView Grid.Column="1" ItemsSource="{Binding Path=FieldDescriptions}">
<ListView.ItemTemplate>
<DataTemplate>
<local:Node DataContext="{Binding Converter={StaticResource ModelConverter}}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
的主窗口中的數據上下文被設置到一個新的RD(),其被定義如下: RD
public class RD
{
private IEnumerable<IFieldDescription> GetTestData()
{
yield return new FieldDescription("String", true);
yield return new FieldDescription("Integer", false);
yield return new FieldDescription("Double", false);
yield return new FieldDescription("Date", false);
yield return new FieldDescription("Enum", false);
}
public virtual ObservableCollection<IFieldDescription> FieldDescriptions
{
get { return new ObservableCollection<IFieldDescription>(GetTestData()); }
}
}
我的任何轉換器目前被定義爲:
public class ModelToViewConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return null;
if (value is IFieldDescription)
{
NodeModel model = new NodeModel((IFieldDescription)value);
return new Node(model);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
請,永遠不要設置的一些例子'this.DataContext'在Control的構造函數中使用。用這種方法你會用自己的腿打自己。用於控制的'DataContext'應該只從外部設置,通常從其父級設置。有一天在構造函數中設置了'this.DataContext = ...',你會遇到一個噩夢,試圖理解「爲什麼我的綁定不起作用在這個控件上」 – Snowbear 2012-02-17 16:07:31
@Snowbear:感謝評論,建議指出。我仍然試圖讓我的頭腦圍繞WPF的基礎知識,所以很高興承認我可能犯了一些錯誤。 – Ian 2012-02-17 16:29:32