none
WPF. C#. Multibinding к DataView RRS feed

  • Общие обсуждения

  • namespace DataTableBindings

    {

    public partial class MainWindow : Window

    {

    public MainWindow()

    {

    InitializeComponent();

    var dtb = new DataTableBuild(); DataTable dataTable = dtb.Get(5, 12); DataView dataView = dataTable.DefaultView; Binding dataTableBinding = new Binding(); dataTableBinding.Source = dataTable; dataTableBinding.Path = new PropertyPath("Rows[3][10]"); txtMyTextColumnDataTable.SetBinding(TextBox.TextProperty, dataTableBinding); dataTableBinding = new Binding(); dataTableBinding.Source = dataTable; dataTableBinding.Path = new PropertyPath("Rows[3][11]"); txtMyTextColumnDataTable2.SetBinding(TextBox.TextProperty, dataTableBinding); MultiBinding multiBinding = new MultiBinding(); multiBinding.Converter = new SumCells(); Binding binding = new Binding(); binding.Source = dataView; binding.Path = new PropertyPath("[3][10]"); multiBinding.Bindings.Add(binding); binding = new Binding(); binding.Source = dataView; binding.Path = new PropertyPath("[3][11]"); multiBinding.Bindings.Add(binding); txtMyTextColumnDataView.SetBinding(TextBox.TextProperty, multiBinding);

    }

    }

    }

    При выполнении выдаёт ошибку "Вызов конструктора для типа "DataTableBindings.MainWindow", удовлетворяющего указанным ограничениям привязки, привел к выдаче исключения." Если подключаю к одному из полей через простой Binding всё работает. Конвертер выполняет суммирование из двух ячеек и выдаёт результат отличный от нуля.

    Порылся в инете нигде не видел multibinding к dataview. Это вообще возможно? (программно). Обязательным условием является запись в DataTabel  и получение из него через DataView данных.

    12 апреля 2013 г. 6:46

Все ответы

  • Если нужна сумма чисел по колонкам или какая другая формула, то можно определить Expression для DataColumn без всяких извращений.

    12 апреля 2013 г. 7:10
    Отвечающий
  • Не подходит, т.к. Expression необходимо использовать на этапе создания DataTable, причём с именнованными, как я понял, колонками. Класс DataTableBuild() генерирует DataTable определенной размерности без именнованных колонок (размерность меняется в зависимости от входных условий). По "координатам" ячеек цепляются textBox для заполнения, а по каким колонкам будет проходить суммирование зарание неизвестно. Это зависит от дополнительных внешних условий. Выше описанный код - это сильно упрощённое моделирование для поиска решения.

    12 апреля 2013 г. 7:42
  • Где вы прочитали, что его нельзя менять во время использования таблицы?
    12 апреля 2013 г. 8:00
    Отвечающий
  • Что использовать вместо ColumnName? Если для DataTable используется обращение вида Rows[i][j] , ну и соотвественно, для DataView просто [i][j]

    12 апреля 2013 г. 8:05
  • Имя у колонки в таблице всегда существует. Если вы его не задали, оно будет создано автоматически с именем Column1..ColumnN. Имя колонки всегда можно найти по индексу её (dataTable.Columns[i].ColumnName).

    Вам нужна формула, в которой вы будете ссылаться не только на разные колонки, но и разные строки?

    12 апреля 2013 г. 8:30
    Отвечающий
  • Именно.

    12 апреля 2013 г. 8:35
  • http://www.codeproject.com/Articles/17853/Implementing-an-Excel-like-formula-engine - попробуйте вот это посмотреть.

    Но скорее всего придется DataTable заполнять своим типом данных, который поддерживает формулы и ссылки на объекты. MultiBinding вас не спасет - будет слишком запутано. + можно воспользоваться парсером формул. Я использовал NCalc.

    12 апреля 2013 г. 8:39
    Отвечающий
  • кстати, dataTable.Columns[10].ColumnName - возвращает 10... ссылку уже смотрю )

    12 апреля 2013 г. 8:49
  • что-то странное получается с Expression. Добавляю колонку

     DataColumn column = new DataColumn("sm",typeof(int));
     column.Expression = "[10] + [11]";
     dataTable.Columns.Add(column);

    если делаю binding к DataTable - всё нормально, показывает ноль (таблица по умолчанию заполнена нулями)

    dataTableBinding = new Binding();
    dataTableBinding.Source = dataTable;
    dataTableBinding.Path = new PropertyPath("Rows[3][sm]");
    txtMyTextColumnDataView.SetBinding(TextBox.TextProperty, dataTableBinding);

    Но в таком виде динамически суммировать не будет, надо подключать DataView

    DataView dataView = dataTable.DefaultView;
    Binding dataViewBinding = new Binding();
    dataViewBinding.Source = dataView;
    dataViewBinding.Path = new PropertyPath("[3][sm]");
    txtMyTextColumnDataView.SetBinding(TextBox.TextProperty, dataViewBinding);

    выдаёт "Вызов конструктора для типа "DataTableBindings.MainWindow", удовлетворяющего указанным ограничениям привязки, привел к выдаче исключения.", если ставлю ссылку на new PropertyPath("[3][11]") исключения нет, динамически отображает изменение в ячейке [3][11].

    DataView "не любит" колнки с Expression?

     
    12 апреля 2013 г. 9:22
  • По идее должно работать. Что написано в последнем вложенном InnerException?
    15 апреля 2013 г. 13:34
    Отвечающий
  • System.InvalidOperationException: Привязка типа TwoWay или OneWayToSource не может работать с доступным только для чтения свойством "sm" типа "System.Data.DataEowView".


    • Изменено rz3rr 16 апреля 2013 г. 6:13
    16 апреля 2013 г. 6:13
  • Попробуйте использовать ToDataView() расширение. Оно создает LinqDataView - возможно он даст больше возможностей.

    Привязку, кстати, можно ещё делать через саму таблицу:

    new PropertyPath("Table[3][sm]")

    Правда не уверен, что это поможет.

    16 апреля 2013 г. 13:06
    Отвечающий
  • Видимо Вы имели ввиду что-то типа

    DataView view = query.AsDataView();
    
    Вариант с new PropertyPath("Table[3][sm]") избавляет от генерации исключения.... но ничего не выводит. Опробую вариант с LinqDataView, если это упростит решение....

    16 апреля 2013 г. 14:54
  • Да, я имел ввиду AsDataView - просто попробуйте. Не получится, значит не получится. Правда идей больше пока нет.
    16 апреля 2013 г. 17:40
    Отвечающий
  • EnumerableRowCollection<DataRow> query = from c in dataTable.AsEnumerable()
    select c;
    DataView dataView = query.AsDataView();

    работает сразу со всеми полями, вычислительное поле тут не вставить из-за "EnumerableRowCollection<DataRow>" (может я и не прав, но не получилось).

    Сделал так

    var query = from order in dataTable.AsEnumerable()
                       select new
                           {
                              a = order.Field<int>(10),
                              b = order.Field<int>(11),
                              sum = order.Field<int>(10) + order.Field<int>(11)
                           };
    DataTable table = new DataTable();
     table.Columns.Add("a");
     table.Columns.Add("b");
     table.Columns.Add("sum");
     foreach (var t in query)
           {
            table.Rows.Add(t.a, t.b , t.sum);
           }
     DataView dataView = table.DefaultView;

    но так пропадает "динамика" и создаётся еще одна dataTable

    Вышел из положения, но получилось достаточно сложно и не гибко: контрол по изменению своего значения запускает дополнительно класс с обсчетом данных в таблице и вставкой результатов суммирования в ячейку "биндящееся" к контролу, отображающее сумму.

    17 апреля 2013 г. 13:00
  • Уважаемый пользователь!

    В вашей теме отсутствует активность в течение последних 5 дней. При отсутствии каких-либо действий в течение 2 последующих дней, тема будет переведена в разряд обсуждений. Вы можете возобновить дискуссию, просто оставив сообщение в данной теме

    22 апреля 2013 г. 7:26
    Модератор