【问题标题】:Binding selected item from Listbox with datatemplate将列表框中的选定项目与数据模板绑定
【发布时间】:2016-03-31 20:10:31
【问题描述】:

我有一个带有问题和答案的ListBox,它从Database 获取数据。现在我想显示或编辑“列表框”中选定行的数据,但我有问题如何到达这一行。

编辑。图像显示我想要做什么: http://imgur.com/5NHjYA4

我的观点:

<Window x:Class="QuizMaker.MainWindow"
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>

    <Window.Resources>
        <DataTemplate x:Key="QuestionsTemplate">
            <Grid>      
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="320" />
                    <ColumnDefinition Width="120" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="20" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding Path=Question}" FontWeight="Bold" />
                <TextBlock Grid.Column="1" Text="{Binding Path=AnswerA}" />
                <TextBlock Grid.Column="2" Text="{Binding Path=AnswerB}"/>
                <TextBlock Grid.Column="3" Text="{Binding Path=AnswerC}"/>
                <TextBlock Grid.Column="4" Text="{Binding Path=AnswerD}"/>
                <TextBlock Grid.Column="5" Text="{Binding Path=RightAnswer}" FontWeight="Bold"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>

    <Grid>        
        <ListBox  DataContext="{Binding MyDataSet}" 
                  x:Name="listBox"   
                  ItemsSource="{Binding Path=QuestionTable}"
                  ItemTemplate="{StaticResource QuestionsTemplate}" 
                  SelectedItem="{Binding SelectedItemString}"             
        />

    </Grid>
</Window>

还有ViewModel(我剪掉了大部分属性)

{
    class MainViewModel
    {
        private string _appPath;

        private MainModel _MainModel;


        public MainViewModel()
        {
            _MainModel = new MainModel();


            mdbFile = Path.Combine(AppDataPath, "QuestionBase.mdb");
            connString = $"Provider=Microsoft.Jet.OLEDB.4.0; Data Source={mdbFile}";
            conn = new OleDbConnection(connString);

            adapter = new OleDbDataAdapter("SELECT * FROM QuestionTable;", conn);

            MyDataSet = new DataSet();
            adapter.Fill(MyDataSet, "QuestionTable");


        }

        private void AddToDB()
        {
            conn.Open();
            OleDbCommand myCommand = new OleDbCommand("Insert INTO QuestionTable ( Question, AnswerA, AnswerB, AnswerC, AnswerD ) Values(@Question, @AnswerA, @AnswerB, @AnswerC, @AnswerD)", conn);
            myCommand.Parameters.Add("@Question", OleDbType.BSTR).Value = Question;
            myCommand.Parameters.Add("@Question", OleDbType.BSTR).Value = AnswerA;
            myCommand.Parameters.Add("@Question", OleDbType.BSTR).Value = AnswerB;
            myCommand.Parameters.Add("@Question", OleDbType.BSTR).Value = AnswerC;
            myCommand.Parameters.Add("@Question", OleDbType.BSTR).Value = AnswerD;
            myCommand.ExecuteNonQuery();
            conn.Close();
        }

        private string AppDataPath
        {
            get
            {
                if (string.IsNullOrEmpty(_appPath))
                {
                    _appPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
                }
                return _appPath;
            }
        }

        public OleDbDataAdapter adapter
        {
            get
            {
                return _MainModel.adapter;
            }
            set
            {
                _MainModel.adapter = value;
                OnPropertyChanged("adapter");
            }
        }
        public DataSet MyDataSet
        {
            get
            {
                return _MainModel.MyDataSet;
            }
            set
            {
                _MainModel.MyDataSet = value;
                OnPropertyChanged("MyDataSet");
            }
        }
    public string SelectedItemString
    {
        get
        {
            return _MainModel.SelectedItemString;
        }
        set
        {
            _MainModel.SelectedItemString = value;
            OnPropertyChanged("SelectedItemString");
        }
    }


        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }





    }
}

【问题讨论】:

  • 你到底在问什么?如何从数据库中获取数据?
  • 这可能是题外话,但在您的 AddToDB() 方法中,您似乎有一个复制/粘贴错误,您将 @Question 参数设置了五次,而其他四个参数根本没有.
  • 不,我从数据库中获取数据,它在列表框中显示得很好。现在我想单击列表框中的一行,然后我想编辑(将每个字段复制到文本框或某事)或删除选定的行。

标签: c# wpf mvvm


【解决方案1】:

抱歉,我无法添加评论。我希望您的要求是在 TextBox 中显示所选项目的值,并在您从 TextBox 更改值时将相同的值更新到您的集合中(在您的情况下为 DataTable)。如果这是您的要求,请像这样更改您的 TextBox 绑定

<TextBox x:Name="ValueText" Text="{Binding SelectedItem.ColumnName, ElementName=listBox, UpdateSourceTrigger=PropertyChanged}" />

我不知道您为什么要将 SelectedItem 绑定到字符串类型 SelectedItemString 属性。它将根据您的来源创建绑定错误。

【讨论】:

    【解决方案2】:

    将您的SelectedItemString 属性更改为DataRow,并将您的其他控件绑定到该属性。

    例如,

    public DataRow SelectedItem
    {
        get
        {
            return _MainModel.SelectedItem;
        }
        set
        {
            _MainModel.SelectedItem = value;
            OnPropertyChanged("SelectedItem");
        }
    }
    

    在 XAML 中应该是这样的:

    <Window x:Class="QuizMaker.MainWindow"
        <Window.DataContext>
            <local:MainViewModel />
        </Window.DataContext>
    
        <Window.Resources>
            <DataTemplate x:Key="QuestionsTemplate">
                <Grid>      
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="320" />
                        <ColumnDefinition Width="120" />
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="100" />
                        <ColumnDefinition Width="20" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Grid.Column="0" Text="{Binding Path=Question}" FontWeight="Bold" />
                    <TextBlock Grid.Column="1" Text="{Binding Path=AnswerA}" />
                    <TextBlock Grid.Column="2" Text="{Binding Path=AnswerB}"/>
                    <TextBlock Grid.Column="3" Text="{Binding Path=AnswerC}"/>
                    <TextBlock Grid.Column="4" Text="{Binding Path=AnswerD}"/>
                    <TextBlock Grid.Column="5" Text="{Binding Path=RightAnswer}" FontWeight="Bold"/>
                </Grid>
            </DataTemplate>
        </Window.Resources>
    
        <DockPanel>   
            <ContentControl Content="{Binding SelectedItem}" 
                            ContentTemplate="{StaticResource QuestionsTemplate}" 
                            DockPanel.Dock="Top" />  
    
            <ListBox  DataContext="{Binding MyDataSet}" 
                      x:Name="listBox"   
                      ItemsSource="{Binding Path=QuestionTable}"
                      ItemTemplate="{StaticResource QuestionsTemplate}" 
                      SelectedItem="{Binding SelectedItem}"             
            />
    
        </DockPanel>
    </Window>
    

    此外,如果您真的不想更改跟踪所选项目的方式,也可以直接绑定到 listBox.SelectedItem,例如 Davys said

    <ContentControl Content="{Binding ElementName=listBox, Path=SelectedItem}" 
                    ContentTemplate="{StaticResource QuestionsTemplate}" 
                    DockPanel.Dock="Top" />  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      • 1970-01-01
      • 2011-05-18
      • 2016-07-19
      • 2013-02-23
      • 1970-01-01
      相关资源
      最近更新 更多