Привязка просмотра списка wpf к набору данных .... Возможно ..? - PullRequest
4 голосов
/ 07 июня 2009

Я изо всех сил пытался перейти на Wpf, я просто застрял при попытке привязать данные к lsitview. Я хочу привязать представление списка к набору данных (набор данных, потому что данные, которые я хочу отобразить в столбцах, принадлежат разным таблицам). Прикрепление примера кода, с которым я пытаюсь. Это работает хорошо, но в списке отображается только одна строка. Может быть, это неправильно. Может кто-нибудь подсказать мне. Все доступные образцы используют datatables.None указывает на привязку к набору данных. .. любой вклад будет высоко оценен ... заранее спасибо

Мой Xaml

<Grid>
<TextBox Text="" Height="20" Width="100" HorizontalAlignment="Left" Margin="15,13,0,0" VerticalAlignment="Top"></TextBox>
<TextBox Text="" Height="20" Width="100" HorizontalAlignment="Left" Margin="15,42,0,0" VerticalAlignment="Top"></TextBox>
<ListView Margin="15,89,63,73" Name="lst" ItemsSource="{Binding}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name"  DisplayMemberBinding="{Binding Path=T1/Name}"></GridViewColumn>
            <GridViewColumn Header="Place" DisplayMemberBinding="{Binding Path=T2/Name}"></GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>
<!--<Button Height="19" HorizontalAlignment="Right" Name="button2" VerticalAlignment="Top" Width="46" Margin="0,42,63,0" Click="button2_Click">Add</Button>-->
<Button Height="19" HorizontalAlignment="Right" Name="button1" VerticalAlignment="Top" Width="46" Click="button1_Click" Margin="0,43,63,0">Add</Button>

Мой код

 Dt1 = new DataTable("T1");
        Dt1.Columns.Add("Name");
        Dt1.Rows.Add("abc1");
        Dt1.Rows.Add("abc2");
        Dt2 = new DataTable("T2");
        Dt2.Columns.Add("Name");
        Dt2.Rows.Add("xyz1");
        Dt2.Rows.Add("xyz1");
        Ds = new DataSet();
        Ds.Tables.Add(Dt1);
        Ds.Tables.Add(Dt2);

        lst.DataContext = Ds;

Ответы [ 4 ]

4 голосов
/ 08 июня 2009

Привет, я полностью согласен с Энди и Томасом. Они оба объяснили концепцию элегантно.

Я показываю только шаги, чтобы сделать то же самое только с набором данных .

MVVM (ModelView ViewModel) Я здесь не обсуждаю.

Xaml выглядит так

<Grid Name="myGrid" ShowGridLines="False">


    <Label Height="28" Margin="12,5,0,0" Name="lblName" VerticalAlignment="Top" HorizontalAlignment="Left" Width="55">Name</Label>
    <TextBox Height="23" Margin="73,8,85,0" Name="txtName" VerticalAlignment="Top" />
    <Label Height="28" Margin="12,39,0,0" Name="lblPlace" VerticalAlignment="Top" HorizontalAlignment="Left" Width="55">Place</Label>
    <TextBox Height="23" Margin="73,44,85,0" Name="txtPlace" VerticalAlignment="Top" />
    <Button Height="23" HorizontalAlignment="Left" Margin="20,82,0,0" Name="btnAddRecord" VerticalAlignment="Top" Width="75" Click="btnAddRecord_Click">Add Record</Button>
    <ListView Margin="31,119,27,45" Name="listView" *ItemsSource="{Binding}"*>

        <ListView.View>

            <GridView>

                <GridViewColumn Header="Name"  DisplayMemberBinding="{Binding Name}"/>

                <GridViewColumn Header="Place" DisplayMemberBinding="{Binding Place}"/>


            </GridView>
        </ListView.View>
    </ListView>
</Grid>

В файле .CS создайте набор данных

private DataSet MyDataSet()
    {
        DataTable dtInformation1 = new DataTable();
        dtInformation1.Columns.Add("Name");
        dtInformation1.Columns.Add("Place");
        dtInformation1.Rows.Add(txtName.Text, txtPlace.Text);


        DataTable dtInformation2 = new DataTable();
        dtInformation2.Columns.Add("Name");
        dtInformation2.Columns.Add("Place");
        dtInformation2.Rows.Add(txtName.Text + "2", txtPlace.Text + "2");

        DataSet Ds = new DataSet();
        Ds.Tables.Add(dtInformation1);
        Ds.Tables.Add(dtInformation2);
        return Ds;
    }

Далее в событии нажатия кнопки напишите следующее

private void btnAddRecord_Click (отправитель объекта, RoutedEventArgs e)

    {

        **listView.ItemsSource = MyDataSet().Tables[0].DefaultView;
              - OR - 
         listView.ItemsSource = MyDataSet().Tables[1].DefaultView;**
    }

N.B. ~ Вы не можете назначить источник набора данных ListView.

Почему? Вы можете спросить? Простыми словами, набор данных представляет собой набор таблиц данных.

Предположим, у вас есть 5 различных таблиц данных. И скажите, что ни одно из имен столбцов, ни номеров столбцов не совпадают.

Теперь вы назначили все эти данные в свой набор данных. Как источник управления узнает, с каким источником он должен связываться?

Для преодоления такой ситуации либо создайте настраиваемую таблицу данных, в которой будут все столбцы этих дискретных таблиц данных, и присвойте значения этой настраиваемой таблице, а затем свяжите ее с источником.

Или вам нужно явно указать таблицу данных в источнике данных

Но я всегда предпочитаю использовать шаблон MVVM для такого рода операций.

2 голосов
/ 07 июня 2009

Я не уверен, что вы пытаетесь сделать здесь ... Это ожидаемый результат?

abc1    xyz1
abc2    xyz2

Нет связи между вашими таблицами, поэтому система привязки не может угадать, какую строку T1 вы хотите связать с какой строкой T2 ... Вы должны либо поместить все данные в одну таблицу, либо использовать DataRelation между двумя таблицами (но для этого потребуются дополнительные поля для соединения). Затем вы должны установить DataTable как ItemsSource, а не DataSet.

Кроме того, вы можете создать выделенный класс для хранения данных, как предложил Энди

1 голос
/ 04 мая 2011

Это сработало для меня.

public partial class MainWindow : Window
{

   public  ObservableCollection<DataTable> _observableCollection =
   new ObservableCollection<DataTable>();

    public MainWindow()
    {
        InitializeComponent();

        DataTable dt1 = new DataTable();
        dt1.Columns.Add("OrderID");
        dt1.Columns.Add("CustomerID");
        dt1.Columns.Add("ProductID");
        dt1.Rows.Add("test1", "test2", "test3");

        DataTable dt2 = new DataTable();
        dt2.Columns.Add("OrderID");
        dt2.Columns.Add("CustomerID");
        dt2.Columns.Add("ProductID");
        dt2.Rows.Add("test4", "test5", "test6");

        _observableCollection.Add(dtInformation1);
        _observableCollection.Add(dtInformation2);
    }

    public ObservableCollection<DataTable> _Collection
       { get { return _observableCollection; } }

ListView XAML

<ListView  Height="Auto" 
HorizontalAlignment="Stretch" 
Name="somename" 
ItemsSource="{Binding _Collection}" VerticalAlignment="Stretch" Width="Auto" >

  <GridViewColumn  Header="OrderID" Width="auto" >
      <GridViewColumn.CellTemplate>
          <DataTemplate>
              <Button Tag="{Binding OrderID}" Content="{Binding OrderID}"/>
          </DataTemplate>
      </GridViewColumn.CellTemplate>
  </GridViewColumn>
  <GridViewColumn Width="auto" DisplayMemberBinding="{Binding CustomerID}" Header="CustomerID" />
  <GridViewColumn Width="auto" DisplayMemberBinding="{Binding ProductID}" Header="ProductID" />

1 голос
/ 07 июня 2009

WPF Binding работает от свойств. Например, рассмотрим следующий Person объект:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Затем можно изменить XAML для вашего ListView, чтобы он отображал коллекцию Person объектов, выполнив следующие действия:

<ListView Margin="15,89,63,73" Name="lst" ItemsSource="{Binding}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="First Name"
                DisplayMemberBinding="{Binding Path=FirstName}" />
            <GridViewColumn Header="Last Name"
                DisplayMemberBinding="{Binding Path=LastName}" />
        </GridView>
    </ListView.View>
</ListView>

Это отобразит имя объекта в первом столбце и их фамилию во втором столбце (при условии, что DataContext из ListView является набором Person объектов).

Теоретически, чтобы связать значения в DataTable с ListView, вы можете установить ItemsSource для DataTable s Rows. Проблема заключается в том, что класс DataRow не предоставляет свойства для своих столбцов - есть только свойство Item, которое принимает аргумент, определяющий строку. Насколько мне известно, XAML не поддерживает свойства, которые принимают аргументы, поэтому я не думаю, что можно использовать DataTable в качестве ItemsSource для ListView.

Однако у вас есть другие варианты. Вы можете создать строго типизированный DataSet, который предоставит DataTable со свойством для каждого столбца. Затем вы можете привязать каждый GridViewColumn к правильному свойству.

Другой подход заключается в том, чтобы вообще не использовать DataTable. Слой данных все равно будет загружать данные из вашего источника в DataTable, но затем преобразует эти данные в обычные объекты. Вы можете создать экземпляр ObservableCollection , добавить в него каждый из объектов и затем связать с ним ListView. Каждый GridViewColumn будет просто привязываться к соответствующему свойству объектов.

Обновлен:

В ответ на дополнительный вопрос ОП:

Могу ли я использовать xsd для этой цели? содержит свойство для каждого объекта данных ..

Вам нужно больше, чем просто свойство для DataTable. Вам также понадобится свойство для каждого значения в каждой строке DataTable. В противном случае отсутствует свойство для привязки столбцов ListView.

...