C# 使用ViewModel在xaml中显示列表
我有一个名为“UserControllerIo”的用户控件,它的功能如下:C# 使用ViewModel在xaml中显示列表,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个名为“UserControllerIo”的用户控件,它的功能如下: public ObservableCollection<string> Messages { get; set; } public UserControllerIo() { Messages = new ObservableCollection<string>(); InitializeComponent();
public ObservableCollection<string> Messages { get; set; }
public UserControllerIo()
{
Messages = new ObservableCollection<string>();
InitializeComponent();
IoComponentViewModel.Instance = new IoComponentViewModel();
Label1.DataContext = IoComponentViewModel.Instance;
Messages.Add(Label1.Text);
}
我调用来填充另一个类上的列表,如下所示:
case x:
IoComponentViewModel.Instance.XState = msg;
break;
我的问题是,它没有显示在我的Listview中,尽管我可以在标签中看到它。你能告诉我怎么做吗。谢谢。我不知道从提供的代码中我对您的任务有多了解,但请看这个实现变体 IoComponentViewModel:
public class IoComponentViewModel : INotifyPropertyChanged
{
public static IoComponentViewModel Instance { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private string _xState;
public string XState
{
get { return _xState; }
set
{
if (_xState == value)
return;
XStates.Add(_xState = value);
OnPropertyChanged($"XState");
}
}
public ObservableCollection<string> XStates { get; } = new ObservableCollection<string>();
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<Grid x:Name="PART_Grid">
<Grid.DataContext>
<local:IoComponentViewModel/>
</Grid.DataContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--<Label>-->
<TextBlock x:Name="Label1" TextWrapping="WrapWithOverflow"
Text="{Binding XState, Mode=OneWay}">
</TextBlock>
<!--</Label>-->
<ListView Grid.Row="1"
x:Name="ListView"
ItemsSource="{Binding XStates}" />
</Grid>
//public ObservableCollection<string> Messages { get; set; }
public UserControllerIo()
{
//Messages = new ObservableCollection<string>();
InitializeComponent();
// IoComponentViewModel.Instance = new IoComponentViewModel();
//Label1.DataContext = IoComponentViewModel.Instance;
IoComponentViewModel.Instance = (IoComponentViewModel)PART_Grid.DataContext;
//Messages.Add(Label1.Text);
}
公共类IoComponentViewModel:INotifyPropertyChanged
{
公共静态IoComponentViewModel实例{get;set;}
公共事件属性更改事件处理程序属性更改;
私有字符串xState;
公共字符串XState
{
获取{return}
设置
{
如果(xState==值)
回来
添加(xState=value);
OnPropertyChanged($“XState”);
}
}
public ObservableCollection XStates{get;}=new ObservableCollection();
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
XAML:
public class IoComponentViewModel : INotifyPropertyChanged
{
public static IoComponentViewModel Instance { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private string _xState;
public string XState
{
get { return _xState; }
set
{
if (_xState == value)
return;
XStates.Add(_xState = value);
OnPropertyChanged($"XState");
}
}
public ObservableCollection<string> XStates { get; } = new ObservableCollection<string>();
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<Grid x:Name="PART_Grid">
<Grid.DataContext>
<local:IoComponentViewModel/>
</Grid.DataContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--<Label>-->
<TextBlock x:Name="Label1" TextWrapping="WrapWithOverflow"
Text="{Binding XState, Mode=OneWay}">
</TextBlock>
<!--</Label>-->
<ListView Grid.Row="1"
x:Name="ListView"
ItemsSource="{Binding XStates}" />
</Grid>
//public ObservableCollection<string> Messages { get; set; }
public UserControllerIo()
{
//Messages = new ObservableCollection<string>();
InitializeComponent();
// IoComponentViewModel.Instance = new IoComponentViewModel();
//Label1.DataContext = IoComponentViewModel.Instance;
IoComponentViewModel.Instance = (IoComponentViewModel)PART_Grid.DataContext;
//Messages.Add(Label1.Text);
}
代码隐藏:
public class IoComponentViewModel : INotifyPropertyChanged
{
public static IoComponentViewModel Instance { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private string _xState;
public string XState
{
get { return _xState; }
set
{
if (_xState == value)
return;
XStates.Add(_xState = value);
OnPropertyChanged($"XState");
}
}
public ObservableCollection<string> XStates { get; } = new ObservableCollection<string>();
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<Grid x:Name="PART_Grid">
<Grid.DataContext>
<local:IoComponentViewModel/>
</Grid.DataContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--<Label>-->
<TextBlock x:Name="Label1" TextWrapping="WrapWithOverflow"
Text="{Binding XState, Mode=OneWay}">
</TextBlock>
<!--</Label>-->
<ListView Grid.Row="1"
x:Name="ListView"
ItemsSource="{Binding XStates}" />
</Grid>
//public ObservableCollection<string> Messages { get; set; }
public UserControllerIo()
{
//Messages = new ObservableCollection<string>();
InitializeComponent();
// IoComponentViewModel.Instance = new IoComponentViewModel();
//Label1.DataContext = IoComponentViewModel.Instance;
IoComponentViewModel.Instance = (IoComponentViewModel)PART_Grid.DataContext;
//Messages.Add(Label1.Text);
}
//公共ObservableCollection消息{get;set;}
public UserControllerIo()
{
//消息=新的ObservableCollection();
初始化组件();
//IoComponentViewModel.Instance=新IoComponentViewModel();
//Label1.DataContext=IoComponentViewModel.Instance;
IoComponentViewModel.Instance=(IoComponentViewModel)PART_Grid.DataContext;
//Messages.Add(Label1.Text);
}
我最初误解了这个问题。有两个问题。列表未绑定到视图模型,因此需要元素引用
<UserControl x:Class="StackOverflow.UserControllerIo"
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:StackOverflow"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
x:Name="MyUserControl"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label>
<TextBlock Foreground="Black" x:Name="Label1" TextWrapping="WrapWithOverflow"
Text="{Binding Path=XState, Mode=OneWay}">
</TextBlock>
</Label>
<ListView Grid.Row="1"
x:Name="ListView"
ItemsSource="{Binding Messages, ElementName=MyUserControl}" >
</ListView>
</Grid>
第二,在向数据绑定添加Label1.Text的地方,还没有准备好。因此,在读取文本之前,您需要等待绑定,例如,在加载事件中,如下所示:
public partial class UserControllerIo : UserControl
{
public ObservableCollection<string> Messages { get; set; }
public UserControllerIo()
{
Messages = new ObservableCollection<string>();
InitializeComponent();
IoComponentViewModel.Instance = new IoComponentViewModel();
Label1.DataContext = IoComponentViewModel.Instance;
IoComponentViewModel.Instance.XState = "Something";
Loaded += UserControllerIo_Loaded;
}
private void UserControllerIo_Loaded(object sender, RoutedEventArgs e)
{
Messages.Add(Label1.Text);
}
}
public部分类UserControllerIo:UserControl
{
公共ObservableCollection消息{get;set;}
public UserControllerIo()
{
消息=新的ObservableCollection();
初始化组件();
IoComponentViewModel.Instance=新IoComponentViewModel();
Label1.DataContext=IoComponentViewModel.Instance;
IoComponentViewModel.Instance.XState=“Something”;
已加载+=已加载UserControllerIo_;
}
已加载private void UserControllerIo_(对象发送方,路由目标)
{
Messages.Add(Label1.Text);
}
}
编辑:
我的第一个测试误导了我,使用int属性进行测试,以便在运行时向列表中添加值。
无论如何,ObservableCollection都会更新强>
问题在于如何声明Messages属性。如果控件上有属性,则该属性必须是依赖项属性才能通知UI
替换
public ObservableCollection<string> Messages { get; set; }
publicobservableCollection消息{get;set;}
与
公共可观察收集消息
{
get{return(ObservableCollection)GetValue(MessagesProperty);}
set{SetValue(MessagesProperty,value);}
}
公共静态只读从属属性MessagesProperty=
DependencyProperty.Register(“消息”、typeof(ObservableCollection)、typeof(UserControllerIo)、new PropertyMetadata(null));
你应该没事的
或
您可以在UserControl类上更改imlpement InotifyProperty
别忘了维护@Clemens关于绑定的评论
ItemsSource=“{Binding Messages,RelativeSource={RelativeSource antestortype=UserControl}”
所以让我检查一下我是否理解这一点,您正在更改XState
的值,但希望列表值也会更新?如果只有一列,请使用列表框。下面是一个非常类似的工作示例:ItemsSource绑定没有源对象。请尝试ItemsSource=“{Binding Messages,RelativeSource={RelativeSource AncestorType=UserControl}}“
。即使如此,调用Messages.Add(Label1.Text);
在构造函数中,可能太早了,因为标签的文本属性可能尚未设置。也可能有这样的错误原因。在UserControl中,您创建了IoComponentViewModel的一个实例,而在IoComponentViewModel.instance.XState=msg中,您正在转向另一个实例。请检查是否更改了IoComponentViewModel。在代码中的某个位置的station属性?