Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用ViewModel在xaml中显示列表_C#_Wpf_Mvvm - Fatal编程技术网

C# 使用ViewModel在xaml中显示列表

C# 使用ViewModel在xaml中显示列表,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个名为“UserControllerIo”的用户控件,它的功能如下: public ObservableCollection<string> Messages { get; set; } public UserControllerIo() { Messages = new ObservableCollection<string>(); InitializeComponent();

我有一个名为“UserControllerIo”的用户控件,它的功能如下:

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属性?