我对 MVVM 很陌生,所以请耐心等待。
我正在开发一个包含联系人列表的应用程序。我使用以下模型定义了一个联系人用户控件:
public class Client
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public int CustomerID { get; set; }
public string FullName
{
get
{
string result = FirstName;
if (string.IsNullOrEmpty(result))
result = MiddleName;
else if(!string.IsNullOrEmpty(MiddleName))
result += string.Format(" {0}", MiddleName);
if (string.IsNullOrEmpty(result))
result = LastName;
else if (!string.IsNullOrEmpty(LastName))
result += string.Format(" {0}", LastName);
if (string.IsNullOrEmpty(result))
result = "";
return result;
}
}
}
以及以下 ViewModel:
public class ClientViewModel : ObservableObject
{
public Client Customer
{
get
{
return _customer;
}
set
{
_customer = value;
RaisePropertyChangedEvent("Customer");
}
}
public string FullName { get { return _customer.FullName; } }
public string PhoneNumber { get { return _customer.PhoneNumber; } }
public string Address1 { get { return _customer.Address1; } }
public string Address2 { get { return _customer.Address2; } }
public string City { get { return _customer.City; } }
public string State { get { return _customer.State; } }
public string ZipCode { get { return _customer.ZipCode; } }
Client _customer = new Client();
}
以及以下 View :
<UserControl x:Class="LawnCareManager.Views.ClientView"
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:local="clr-namespace:LawnCareManager.ViewModels"
mc:Ignorable="d"
d:DesignHeight="180" d:DesignWidth="300">
<UserControl.DataContext>
<local:ClientViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Label Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="Name: "/>
<Label Grid.Row="0"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding FullName}"/>
<Label Grid.Row="1"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="Phone Number: "/>
<Label Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding PhoneNumber}"/>
<Label Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="Address 1: "/>
<Label Grid.Row="2"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding Address1}"/>
<Label Grid.Row="3"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="Address 2: "/>
<Label Grid.Row="3"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding Address2}"/>
<Label Grid.Row="4"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="City: "/>
<Label Grid.Row="4"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding City}"/>
<Label Grid.Row="5"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="State: "/>
<Label Grid.Row="5"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding State}"/>
<Label Grid.Row="6"
Grid.Column="0"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Margin="10,0,0,0"
Content="Zip Code: "/>
<Label Grid.Row="6"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10,0,0,0"
Content="{Binding ZipCode}"/>
</Grid>
</UserControl>
现在,我想创建一个用户控件,其中包含在下面的 ViewModel 中定义的联系人列表:
public class ClientsListViewModel : ObservableObject
{
public ObservableCollection<ClientViewModel> Clients
{
get { return _clients; }
set { _clients = value; }
}
ObservableCollection<ClientViewModel> _clients = new ObservableCollection<ClientViewModel>();
public ClientsListViewModel()
{
ClientViewModel client = new ClientViewModel();
client.Customer.FirstName = "John";
client.Customer.LastName = "Doe";
client.Customer.PhoneNumber = "555-555-5555";
client.Customer.Address1 = "1234 Fake Street";
client.Customer.City = "Springfield";
_clients.Add(client);
}
}
以及下面的 View :
<UserControl x:Class="LawnCareManager.Views.ClientsListView"
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:local="clr-namespace:LawnCareManager.ViewModels"
xmlns:views="clr-namespace:LawnCareManager.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<local:ClientsListViewModel/>
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Label Content="Contacts"
Grid.Row="0"
Grid.Column="0"/>
<ListView Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2" ItemsSource="{Binding Clients}" x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<views:ClientView DataContext="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</UserControl>
问题是ClientsListView中的ClientView ListViewItems没有正确绑定(bind)到ClientViewModels的ObservableCollection。如果我添加更多 ClientViewModels,则正确数量的 ClientViews 会显示在列表中,但 ClientView 中的任何标签都没有填充。
有人可以告诉我我做错了什么吗?非常感谢任何反馈!
最佳答案
这里的问题是您正在 InitializeComponent 方法中为客户端 View 构建数据上下文。这是由于 Xaml 中的静态声明。您可以通过将这行代码添加到 ClientView 构造函数来凭经验证明这一点...
var dc = this.DataContext;
并观察它是在“错误的时间”用空值创建的。
如果您在 ClientView.xaml 中更改这些行...
<UserControl.DataContext>
<genericMvvm1:ClientViewModel/>
</UserControl.DataContext>
对这个...
<!--<UserControl.DataContext>
<genericMvvm1:ClientViewModel/>
</UserControl.DataContext>-->
您将看到您的客户以您期望的方式填充和显示。您需要更改设计策略以考虑 InitializeComponent 的行为方式,但这个答案会让您“陷入困境”。
关于c# - 将 ListView 与包含 UserControls 的 DataTemplates 绑定(bind)到 MVVM 中的 ViewModels,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23353767/