【问题标题】:WPF MVVM ComboBox data bindingWPF MVVM ComboBox 数据绑定
【发布时间】:2019-06-23 02:42:35
【问题描述】:

我正在尝试创建一个简单的 WPF 应用程序并将数据绑定到组合框,但我没有任何运气。我的 PeriodList 填充得很好,但没有绑定到组合框。我需要在 XAML 中还是在后面的代码中设置 DataContext?请帮忙,我很困惑。

这是我的 XAML

<UserControl x:Class="FinancialControlApp.KeyClientReportView"
             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:FinancialControlApp"
             mc:Ignorable="d" 
             d:DesignHeight="300" Width="630">

    <UserControl.Resources>
        <!-- DataTemplate (View) -->
        <DataTemplate DataType="{x:Type local:KeyClientReportModel}">
        </DataTemplate>
    </UserControl.Resources>

    <DockPanel Margin="20">
        <DockPanel DockPanel.Dock="Top" VerticalAlignment="Center">
            <TextBlock Margin="10,2" DockPanel.Dock="Left" Text="Start Period" VerticalAlignment="Center" />

            <ComboBox Name="cmbStartPeriod" Margin="10,2" Width="112" VerticalAlignment="Center" ItemsSource="{Binding PeriodList}">
            </ComboBox>

            <TextBlock Margin="10,2" DockPanel.Dock="Left" Text="End Period" VerticalAlignment="Center" />

            <ComboBox Name="cmbEndPeriod" Margin="10,2" Width="112" VerticalAlignment="Center" ItemsSource="{Binding PeriodList}" />

            <!--<Button Content="Save Product" DockPanel.Dock="Right" Margin="10,2" VerticalAlignment="Center"
                        Command="{Binding Path=SaveProductCommand}" Width="100" />-->

            <Button Content="Run" DockPanel.Dock="Left" Margin="10,2" 
                        Command="{Binding Path=GetProductCommand}" IsDefault="True" Width="100" />
        </DockPanel>

        <!--<ContentControl Margin="10" Content="{Binding Path=PeriodName}" />-->
        <ContentControl Margin="10"></ContentControl>
    </DockPanel>
</UserControl>

这是我的模型

     namespace FinancialControlApp
    {
       public class KeyClientReportModel : ObservableObject
       {

        private string _periodName;

        public string PeriodName
        {
            get { return _periodName; }
            set
            {
                if (value != _periodName)
                {
                    _periodName = value;
                    OnPropertyChanged("PeriodName");
                }
            }
        }

        List<KeyClientReportModel> _periodList = new List<KeyClientReportModel>();

        public List<KeyClientReportModel> PeriodList
        {
            get { return _periodList; }
            set
            {
                _periodList = value;
                OnPropertyChanged("PeriodList");
            }
        }
      }
}

这是我的 ViewModel

    namespace FinancialControlApp
{
    public class KeyClientReportViewModel : ObservableObject, IPageViewModel
    {
        private KeyClientReportModel _currentPeriod;
        private ICommand _getReportCommand;
        private ICommand _saveReportCommand;

        public KeyClientReportViewModel()
        {
            GetPeriod();
        }

        public string Name
        {
            get { return "Key Client Report"; }
        }

        public ObservableCollection<KeyClientReportModel> _periodName;
        public ObservableCollection<KeyClientReportModel> PeriodName
        {
            get { return _periodName; }
            set
            {
                if (value != _periodName)
                {
                    _periodName = value;
                    OnPropertyChanged("PeriodName");
                }
            }
        }

        private void GetPeriod()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();
            Helper_Classes.SQLHelper helper = new Helper_Classes.SQLHelper();

            ds = helper.getPeriod();
            dt = ds.Tables[0];
            PeriodName = new ObservableCollection<KeyClientReportModel>();
            foreach (DataRow dr in dt.Rows)
            {
                var period = dr["Period"].ToString();
                if (period != null)
                {
                    PeriodName.Add(new KeyClientReportModel { PeriodName = period });
                }
                //p.PeriodName = dr["Period"].ToString();           
            }
        }
}
}

更新:所以我将一个值转换器附加到调试器中,这就是我所看到的。我明白了

I see 5 items in the list

【问题讨论】:

  • 输出窗口是否有绑定错误?
  • 我没有看到名为“KeyClientReportModel”的公共属性。您只有这种类型的集合,但绑定显示“KeyClientReportModel.PeriodList”。 VIewmodel 会期望类似 public KeyClientReportModel KeyClientReportModel { get; }(类型等于属性名称)
  • 为了更好的实践,我建议不要绑定到模型中的任何属性,而只绑定到视图模型中的属性。您的 ViewModel 必须实现 INotifyPropertyChanged。
  • 我删除了组合框绑定中对 KeyClientModel 的引用,没有运气。 M3212V公共类KeyClientReportViewModel:ObservableObject(该类实现INotifyPropertyChanged)

标签: c# wpf mvvm data-binding combobox


【解决方案1】:

改变

ItemsSource="{Binding KeyClientReportModel.PeriodList}"

收件人:

ItemsSource="{Binding PeriodList}"

确保您的 ViewModel 设置为视图的 DataContext 属性。

将组合框 DisplayMemberPath 设置为 KeyClientReportViewModel 类的属性 Name

或者替代KeyClientReportViewModel 类中的.ToString() 方法,以提供Combobox 项目显示文本。

【讨论】:

  • 干扰你说“确保你的 ViewModel 设置为你的视图的 DataContext 属性。”我怎么做?你能帮忙吗?
  • @user10946936 你在哪里实例化你的 ViewModel?你可能想看看国际奥委会。为简单起见,如果您在用户控件的代码隐藏中实例化您的 ViewModel,您可以将其设置在那里。
  • 在 public partial class KeyClientReportView 后面的代码中: UserControl { public KeyClientReportView() { InitializeComponent(); this.DataContext = new KeyClientReportViewModel(); } }
【解决方案2】:

这对你有帮助

-----查看

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        <!-- To get the ViewModel -->
        xmlns:viewmodels="clr-namespace:WpfApp1.ViewModels"
        Title="MainWindow">
    <Window.DataContext>
        <!-- Assigning the ViewModel to the View -->
        <viewmodels:MainWindowViewModel />
    </Window.DataContext>
    <DockPanel VerticalAlignment="Center"
               DockPanel.Dock="Top">
        <TextBlock Margin="10,2"
                   VerticalAlignment="Center"
                   DockPanel.Dock="Left"
                   Text="Start Period" />
        <ComboBox Name="cmbStartPeriod"
                  Width="112"
                  Margin="10,2"
                  VerticalAlignment="Center"
                  ItemsSource="{Binding PeriodName}" // Items in the ViewModel 
                  DisplayMemberPath="Name"/> // Property to display
    </DockPanel>
</Window>

------- 视图模型

public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        var items = new List<KeyClientReportModel>
        {
            new KeyClientReportModel
            {
                Name = "First",
                Value = 1
            },
            new KeyClientReportModel
            {
                Name = "Second",
                Value = 1
            }
        };

        PeriodName = new ObservableCollection<KeyClientReportModel>(items);
    }

    // You don't need to notify changes here because ObservableCollection 
    // send a notification when a change happens. 
    public ObservableCollection<KeyClientReportModel> PeriodName { get; set; }

}

public class KeyClientReportModel
{
    public int Value { get; set; }
    public string Name { get; set; }
}

【讨论】:

  • 当我根据您的建议更改视图 xmlns:local="clr-namespace:FinancialControlApp.KeyClient" 以指向我的文件夹时,我收到错误 Undefined CLR namespace 。如果我将它保留为 xmlns:local="clr-namespace:FinancialControlApp" 那么我在 DataContext Object Reference not set to an instance of an object 处收到错误
  • 你的 ViewModel 命名空间是什么?
  • 我已经更新了我的问题中的代码。我的 ViewModel 命名空间是 FinancialControlApp
  • 能否添加断点 int GetPeriod() 来检查该方法是否被调用?
  • 是的,GetPeriod() 方法被调用,PeriodName 被所有周期填充。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 2011-10-28
  • 2015-05-24
  • 1970-01-01
  • 2011-05-06
  • 1970-01-01
  • 2020-05-04
相关资源
最近更新 更多