C# WPF打开文件并更新窗口

C# WPF打开文件并更新窗口,c#,wpf,checkbox,data-binding,checkboxlist,C#,Wpf,Checkbox,Data Binding,Checkboxlist,我对WPF比较陌生。我正试图打开一个excel文件,拉取列标题,并将其显示在我的窗口中作为检查列表。现在我在更新我的窗口/清单时遇到问题 这是我在xaml中的内容 <DockPanel Grid.Column="0" Grid.Row="1" Margin="10"> <ListBox ItemsSource="{Binding TagListData}"> <ListBox.ItemTemplate>

我对WPF比较陌生。我正试图打开一个excel文件,拉取列标题,并将其显示在我的窗口中作为检查列表。现在我在更新我的窗口/清单时遇到问题

这是我在xaml中的内容

    <DockPanel Grid.Column="0" Grid.Row="1" Margin="10">
        <ListBox ItemsSource="{Binding TagListData}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <CheckBox IsChecked="{Binding IsTagSelected}" Content="{Binding TagName}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </DockPanel>

这是我在cs代码中的内容。(我现在只使用一个占位符,而不是阅读打开的excel文档,以查看我是否正确地执行了此操作。)

private Excel.Application xlApp;
私人Excel工作簿;
公共ObservableCollection TagListData{get;set;}
公共主窗口()
{
初始化组件();
...
TagListData=新的ObservableCollection();
}
私有无效btnOpenFile_单击(对象发送方,路由目标)
{
OpenFileDialog OpenFileDialog=新建OpenFileDialog();
openFileDialog.Filter=“Excel文件|*.xls;*.xlsx;*.slxm”;
if(openFileDialog.ShowDialog()==true)
{
xlApp=new Excel.Application();
xlWorkbook=xlApp.Workbooks.Open(openFileDialog.FileName);
//填充TagListData
TagListData.Add(新标记类{IsTagSelected=true,TagName=“标记名1”});
}
}
公共类标记类
{
公共字符串标记名{get;set;}
公共布尔值{get;set;}
}    
当我试图打开一个文件来填充我的清单时,什么都没有发生。有人知道我做错了什么吗

我还发现它可以检查项目何时更新,但我想检查列表/集合何时更新。我很难弄明白这一点


谢谢

看起来您还没有设置窗口的DataContext。数据上下文是您绑定到的对象,它不只是自动将绑定连接到您添加到窗口本身的属性

有很多方法可以解决这个问题,最简单(但可能是错误的)解决方法是将其添加到构造函数的末尾:

this.DataContext = this;
但这很奇怪。我建议永远不要这样做。我们通常会创建一个新对象来存放我们想要绑定到的数据。在这种情况下,可以将DataContext设置为TagListData,然后相应地更新绑定

public MainWindow()
{
    InitializeComponent();
    ...

    TagListData = new ObservableCollection<TagClass>();
    this.DataContext = TagListData;
}
public主窗口()
{
初始化组件();
...
TagListData=新的ObservableCollection();
this.DataContext=TagListData;
}
并更新绑定

<DockPanel Grid.Column="0" Grid.Row="1" Margin="10">
    <ListBox ItemsSource="{Binding}"> <!-- note no Path on this binding because the data context of the window IS the collection now -->
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding IsTagSelected}" Content="{Binding TagName}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</DockPanel>


如果要在窗口上绑定其他内容,则将DataContext设置为集合将不起作用。相反,您应该创建一个新类,该类将包含集合和所有其他要绑定到的对象。添加此新类类型的属性,并将其设置为窗口的DataContext。当您使用MVVM模式时,这通常是我们所说的ViewModel。

看起来您还没有设置窗口的DataContext。数据上下文是您绑定到的对象,它不只是自动将绑定连接到您添加到窗口本身的属性

有很多方法可以解决这个问题,最简单(但可能是错误的)解决方法是将其添加到构造函数的末尾:

this.DataContext = this;
但这很奇怪。我建议永远不要这样做。我们通常会创建一个新对象来存放我们想要绑定到的数据。在这种情况下,可以将DataContext设置为TagListData,然后相应地更新绑定

public MainWindow()
{
    InitializeComponent();
    ...

    TagListData = new ObservableCollection<TagClass>();
    this.DataContext = TagListData;
}
public主窗口()
{
初始化组件();
...
TagListData=新的ObservableCollection();
this.DataContext=TagListData;
}
并更新绑定

<DockPanel Grid.Column="0" Grid.Row="1" Margin="10">
    <ListBox ItemsSource="{Binding}"> <!-- note no Path on this binding because the data context of the window IS the collection now -->
        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding IsTagSelected}" Content="{Binding TagName}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</DockPanel>


如果要在窗口上绑定其他内容,则将DataContext设置为集合将不起作用。相反,您应该创建一个新类,该类将包含集合和所有其他要绑定到的对象。添加此新类类型的属性,并将其设置为窗口的DataContext。当您使用MVVM模式时,这通常就是我们所说的ViewModel。

同意Nick的观点;此外,如果不处理
Datacontext
和使用代码隐藏,则使用
Name
属性来标识列表框并在代码隐藏中设置
ItemsSource

<DockPanel Grid.Column="0" Grid.Row="1" Margin="10">
                <!-- Note here-->
                <ListBox Name="TagList"> 
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding IsTagSelected}" Content="{Binding TagName}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </DockPanel>

同意尼克的观点;此外,如果不处理
Datacontext
和使用代码隐藏,则使用
Name
属性来标识列表框并在代码隐藏中设置
ItemsSource

<DockPanel Grid.Column="0" Grid.Row="1" Margin="10">
                <!-- Note here-->
                <ListBox Name="TagList"> 
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding IsTagSelected}" Content="{Binding TagName}"/>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </DockPanel>

非常感谢您,它现在似乎正在按预期工作。INotifyPropertyChanged是否不是更新集合所必需的?这取决于集合和更新的内容。如果使用的是ObservableCollection,则向集合中添加或删除项时不需要INotifyPropertyChanged。如果要用可观察集合的新实例替换集合,则需要INotifyPropertyChange。如果除了选中UI上的复选框之外,还有其他方法可以更改单个项目的标记名或IsTagSelected,那么您的标记类将需要实现InotifyPropertyChange非常感谢,它现在似乎可以正常工作。INotifyPropertyChanged是否不是更新集合所必需的?这取决于集合和更新的内容。如果使用的是ObservableCollection,则向集合中添加或删除项时不需要INotifyPropertyChanged。如果要用可观察集合的新实例替换集合,则需要INotifyPropertyChange。如果有办法更改标记名或IsTag