C# 在XAML中使用简单的数据绑定

C# 在XAML中使用简单的数据绑定,c#,wpf,C#,Wpf,我有一个字符串列表,我想在TabControl的不同选项卡中的几个ComboBox控件中使用这些字符串。字符串列表位于公共可观察集合中。问题是,我无法在XAML文件的部分中显示此集合。以下是全新应用程序中的代码: using System; using System.Collections.ObjectModel; using System.Windows; namespace APX_Interface { public partial class MainWindow : Wind

我有一个字符串列表,我想在TabControl的不同选项卡中的几个ComboBox控件中使用这些字符串。字符串列表位于公共可观察集合中。问题是,我无法在XAML文件的部分中显示此集合。以下是全新应用程序中的代码:

using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace APX_Interface
{
    public partial class MainWindow : Window
    {
         public MainWindow()
        {
            InitializeComponent();
        }       
        
        public ObservableCollection<String> MyStringList; // not initialized yet

        public class NameList : ObservableCollection<String>
        {
            public NameList() : base()
            {
                Add("Willam");
                Add("Isak");
                Add("Victor");
                Add("Jules");
            }
        }
    }
}
使用系统;
使用System.Collections.ObjectModel;
使用System.Windows;
名称空间APX_接口
{
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}       
public observeCollection MyStringList;//尚未初始化
公共类名称列表:ObservableCollection
{
公共名称列表():base()
{
添加(“威廉”);
添加(“Isak”);
添加(“胜利者”);
添加(“朱尔斯”);
}
}
}
}
以下是XAML:

Window x:Class="APX_Interface.MainWindow"
    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:APX_Interface"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">

<Window.Resources>
    <local:MyStringList x:Key="Strings"/>
    <local:NameList x:Key="Names"/>
</Window.Resources>
<Grid>
    
</Grid>
windowx:Class=“APX\u接口.主窗口”
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命名空间:APX_接口”
mc:Ignorable=“d”
Title=“MainWindow”Height=“450”Width=“800”>
当我键入local:时,自动完成显示的唯一内容是App。编译代码时,我会遇到如下错误:

<Window.Resources>
    <local:NameList x:Key="Names"/>
</Window.Resources>
...
<ComboBox ItemsSource="{StaticResource Names}" .../>
<ComboBox ItemsSource="{x:Static local:MainWindow.NameList}" .../>
<Window.Resources>
    <local:StringCollectionINCC x:Key="Strings">
        <sys:String>Willam</sys:String>
        <sys:String>Isak</sys:String>
        <sys:String>Victor</sys:String>
        <sys:String>Jules</sys:String>
    </local:StringCollectionINCC>
    <x:Static Member="local:MyValues.NameList" x:Key="Names"/>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding Mode=OneWay, Source={StaticResource Strings}}" />
    <ListBox Grid.Column="1" ItemsSource="{Binding Mode=OneWay, Source={StaticResource Names}}" />
</Grid>
错误XML命名空间“clr命名空间:APX_接口”中不存在标记“MyStringList”

错误XDG0008命名空间“clr命名空间:APX_接口”中不存在名称“MyStringList”

错误XLS0414未找到类型“local:MyStringList”。验证是否缺少部件引用,以及是否已生成所有引用的部件。 类名称列表也有相同的错误

在看了很多例子和其他讨论之后,我无法指出我遗漏了什么

谢谢你的建议,不幸的是我们还没有解决这个问题。 我在这里发布了代码以及建议的更改和我的评论:

using System;
using System.Collections.ObjectModel;
using System.Windows;

namespace APX_Interface
{
    public  class NameList : ObservableCollection<String>
    // This class is now THE ONLY thing visible in <Window.Resources> 
    // but not any instance of the class.
    {
        public NameList() : base()
        {
        }
    }
      
    public partial class MainWindow : Window
    {
        // This instance of the class is NOT visible in <Window.Resources> ???
        public NameList MyNames { get { return _names;} }

        // nor is this
        public ObservableCollection<String> MyNumbers { get { return _numbers; } }

        // nope
        public NameList _names = null;

        //Neither this one
        public ObservableCollection<String> _numbers = null;

        public MainWindow()
        {
            InitializeComponent();

            // this doesn't make any difference
            DataContext = this;

            _names = new NameList(); 
            _names.Add("fellow");           // populate dynamically

            var _nr = new string[]     // static strings
            {
                "One",
                "Two",
                "etc.",
            };

            _numbers = new ObservableCollection<string>(_nr);
        }
    }
}
使用系统;
使用System.Collections.ObjectModel;
使用System.Windows;
名称空间APX_接口
{
公共类名称列表:ObservableCollection
//该类现在是中唯一可见的对象
//但不是该类的任何实例。
{
公共名称列表():base()
{
}
}
公共部分类主窗口:窗口
{
//类的此实例在???中不可见???
公共名称列表MyNames{get{return}
//这也不是
公共ObservableCollection MyNumbers{get{return}
//没有
公共名称列表_names=null;
//这两个都不是
公共可观测集合_numbers=null;
公共主窗口()
{
初始化组件();
//这没什么区别
DataContext=this;
_名称=新名称列表();
_names.Add(“fellor”);//动态填充
var _nr=新字符串[]//静态字符串
{
“一个”,
“两个”,
“等等”,
};
_数字=新的可观察到的集合(_nr);
}
}
}

您已将
名称列表
声明为MainWindow类中的嵌套类。把它搬出去

除此之外,您不需要在主窗口中声明
MyStringList
字段,并且名称列表也不需要是一个可观察的集合,因为您显然从未在集合初始化后向集合添加或从集合中移除元素

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }       
}

public class NameList : List<String>
{
    public NameList()
    {
        Add("Willam");
        Add("Isak");
        Add("Victor");
        Add("Jules");
    }
}
该资源:

<coll:StringCollection x:Key="Names">
    <sys:String>Willam</sys:String>
    <sys:String>Isak</sys:String>
    <sys:String>Victor</sys:String>
    <sys:String>Jules</sys:String>
</coll:StringCollection>
并将其分配给主窗口的DataContext

private readonly ViewModel viewModel = new ViewModel();

public MainWindow()
{
    InitializeComponent();

    DataContext = viewModel;

    viewModel.NameList.Add("Willam");
    viewModel.NameList.Add("Isak");
    viewModel.NameList.Add("Victor");
    viewModel.NameList.Add("Jules");
}
在XAML中,像这样绑定组合框

<ComboBox ItemsSource="{Binding NameList}" .../>

EDIt2:另一种非常简单的方法可能是静态成员,例如在MainWindow类中,如

public partial class MainWindow : Window
{
    ...

    public static List<string> NameList { get; } = new List<string>
    {
        "Willam", "Isak", "Victor", "Jules"
    };
}
公共部分类主窗口:窗口
{
...
公共静态列表名称列表{get;}=新列表
{
“威廉”,“伊萨克”,“维克多”,“朱尔斯”
};
}
使用的方法如下:

<Window.Resources>
    <local:NameList x:Key="Names"/>
</Window.Resources>
...
<ComboBox ItemsSource="{StaticResource Names}" .../>
<ComboBox ItemsSource="{x:Static local:MainWindow.NameList}" .../>
<Window.Resources>
    <local:StringCollectionINCC x:Key="Strings">
        <sys:String>Willam</sys:String>
        <sys:String>Isak</sys:String>
        <sys:String>Victor</sys:String>
        <sys:String>Jules</sys:String>
    </local:StringCollectionINCC>
    <x:Static Member="local:MyValues.NameList" x:Key="Names"/>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding Mode=OneWay, Source={StaticResource Strings}}" />
    <ListBox Grid.Column="1" ItemsSource="{Binding Mode=OneWay, Source={StaticResource Names}}" />
</Grid>

如果您需要使用local:NameList,那么您必须按照上面的答案进行操作。如果您需要使用MyStringList属性,则必须执行以下操作:

 public partial class MainWindow : Window
        {
            public ObservableCollection<string> _myStringList=new ObservableCollection<string>(); // not initialized yet
            public ObservableCollection<string> MyStringList
            {
                get
                {
                    return _myStringList;
                }
                set
                {
                    _myStringList = value;
                }
            }
    

        public MainWindow()
        {
            
            InitializeComponent();
            fillCombo();
            DataContext = this;
        }
        public void fillCombo()

        {

            MyStringList.Add("Willam");
            MyStringList.Add("Isak");
            MyStringList.Add("Victor");
            MyStringList.Add("Jules");
        }
    }
公共部分类主窗口:窗口
{
public observeCollection _myStringList=new observeCollection();//尚未初始化
公共可观测集合MyStringList
{
得到
{
返回_myStringList;
}
设置
{
_myStringList=值;
}
}
公共主窗口()
{
初始化组件();
fillCombo();
DataContext=this;
}
公共void fillCombo()
{
MyStringList.Add(“Willam”);
MyStringList.Add(“Isak”);
MyStringList.Add(“Victor”);
添加(“朱尔斯”);
}
}
在XML中:

<ComboBox ItemsSource="{Binding MyStringList}" Name="comboBox1"   Margin="34,56,0,0"
              VerticalAlignment="Top"
              Width="200"/>


注意:您还可以在项目中创建usercontrol或customcontrol,然后使用所需元素设计控件。之后,您可以使用创建的控件来控制您想要的任何XML页面。

有几种解决方案,但要选择一种特定的解决方案,您需要给出任务的更多细节

如果需要一个简单的字符串集合,则不需要创建自己的类。 正如@Clements所写的,更好地使用StringCollection

如果需要更改集合的功能(INotifyCollectionChanged接口),可以添加自己的类。 但是您需要在名称空间中构建它,一个
<Window.Resources>
    <local:StringCollectionINCC x:Key="Strings">
        <sys:String>Willam</sys:String>
        <sys:String>Isak</sys:String>
        <sys:String>Victor</sys:String>
        <sys:String>Jules</sys:String>
    </local:StringCollectionINCC>
    <x:Static Member="local:MyValues.NameList" x:Key="Names"/>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding Mode=OneWay, Source={StaticResource Strings}}" />
    <ListBox Grid.Column="1" ItemsSource="{Binding Mode=OneWay, Source={StaticResource Names}}" />
</Grid>
    <ListBox Grid.Column="1" ItemsSource="{x:Static local:MyValues.NameList}" />
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{x:Static local:MyValues.NameList}" />
    <StackPanel Grid.Column="1">
        <TextBox x:Name="tbNew"/>
        <Button Content="Add" Click="Button_Click"/>
    </StackPanel>
</Grid>
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MyValues.NameList.Add(tbNew.Text);
    }
<Window.Resources>
    <local:StringCollectionINCC x:Key="Strings">
        <sys:String>Willam</sys:String>
        <sys:String>Isak</sys:String>
        <sys:String>Victor</sys:String>
        <sys:String>Jules</sys:String>
    </local:StringCollectionINCC>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox ItemsSource="{Binding Mode=OneWay, Source={StaticResource Strings}}" />
    <StackPanel Grid.Column="1">
        <TextBox x:Name="tbNew"/>
        <Button Content="Add" Click="Button_Click"/>
    </StackPanel>
</Grid>
    private void Button_Click(object sender, RoutedEventArgs e)
    {

        StringCollectionINCC list = (StringCollectionINCC)Resources["Strings"];

        list.Add(tbNew.Text);
    }
/// <summary>Executing Delegate.</summary>
/// <param name="parameter">Command parameter.</param>
public delegate void ExecuteHandler(object parameter);
/// <summary>CanExecuting Delegate.</summary>
/// <param name="parameter">Command parameter.</param>
/// <returns><see langword="true"/> - if command execution is allowed.</returns>
public delegate bool CanExecuteHandler(object parameter);

/// <summary>A class implementing the ICommand interface for creating WPF commands.</summary>
public class RelayCommand : ICommand
{
    private readonly CanExecuteHandler _canExecute = CanExecuteDefault;
    private readonly ExecuteHandler _execute;
    private readonly EventHandler _requerySuggested;

    public event EventHandler CanExecuteChanged;

    /// <summary>The constructor of the command.</summary>
    /// <param name="execute">Command Executable Method.</param>
    /// <param name="canExecute">Team Status Method.</param>
    public RelayCommand(ExecuteHandler execute, CanExecuteHandler canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));

        _canExecute = canExecute;

        _requerySuggested = (o, e) => Invalidate();
        CommandManager.RequerySuggested += _requerySuggested;
    }

    /// <summary>The method of invoking an event about a change in command status.</summary>
    public void Invalidate() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);

    public bool CanExecute(object parameter) => _canExecute == null ? true : _canExecute.Invoke(parameter);

    public void Execute(object parameter) => _execute?.Invoke(parameter);

    /// <summary>Default CanExecute Method/</summary>
    /// <param name="parameter">>Command parameter.</param>
    /// <returns>Is always <see langword="true"/>.</returns>
    public static bool CanExecuteDefault(object parameter) => true;
}
/// <summary>ViewModel</summary>
public class MainVM
{
    public ObservableCollection<string> NameList { get; } 
        = new ObservableCollection<string>()
        {
            "Willam",
            "Isak",
            "Victor",
            "Jules"

        };

    private RelayCommand _addCommand;
    public RelayCommand AddCommand => _addCommand 
        ?? (_addCommand = new RelayCommand(AddMethod, AddCanMethod));

    /// <summary>A method that checks that a parameter can be cast to
    /// a string and that string is not empty.</summary>
    /// <param name="parameter">Command parameter.</param>
    /// <returns><see langword="true"/> - if the conditions are met.</returns>
    private bool AddCanMethod(object parameter)
        => parameter is string val
        && !string.IsNullOrWhiteSpace(val);

    /// <summary>Method to add a value to a collection.</summary>
    /// <param name="parameter">Valid command parameter.</param>
    private void AddMethod(object parameter)
        => NameList.Add((string) parameter);
}
/// <summary>Contains all ViewModel. In this case, only one MainVM.</summary>
public class Locator 
{
    public MainVM MainVM { get; } = new MainVM();
}
<Application.Resources>
    <local:Locator x:Key="Locator"/>
</Application.Resources>
<Window ....
        DataContext="{Binding MainVM, Mode=OneWay, Source={StaticResource Locator}}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox ItemsSource="{Binding NameList}" />
        <StackPanel Grid.Column="1">
            <TextBox x:Name="tbNew"/>
            <Button Content="Add"
                    Command="{Binding AddCommand, Mode=OneWay}"
                    CommandParameter="{Binding Text, ElementName=tbNew}"/>
        </StackPanel>
    </Grid>
</Window>