Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 1 элемент управления для нескольких строк  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Доброго времени суток, уважаемые форумчане!
Подскажите, как наиболее красиво решить такую задачу. Нужно привязать к элементу управления (допустим, TextBox) поле из таблицы БД (SQL Server) но только не для 1, а для несколько записей. То есть, программа выбирает n- записей по какому-либо признаку. Если значение в привязываемом поле у всех записей одинаковое, то в TextBox отображается это значение. Если хотя бы у одной записи оно отличается, то в TextBox отображается какие-нибудь символы (например, <...>). Соответственно, при внесении изменений в это TextBox значение этого поля должно изменяться для всех записей.
Хотелось узнать красивый способ для решения этой задачи. Наверняка, это распространенная задача (я часто встречал такие элементы в разном софте). Можно ли её решить с помощью Entity Framework? Хотелось бы получить подсказки именно по WPF, но для WinForms тоже буду рад. Пишу на C#.
10 мар 18, 18:17    [21247094]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 21940
Свой ValueConverter, который выполняет агрегацию любым удобным способом.
10 мар 18, 19:30    [21247143]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
fgarfield
Наверняка, это распространенная задача (я часто встречал такие элементы в разном софте).

Не распространенная. В гугле искали? Скрин сюда с гугла можем?
Если это comboBox выпадающий список то поищите на эти слова.
10 мар 18, 19:38    [21247148]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4030
fgarfield,

примерно так:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;

namespace WpfApp1
{
    public class BaseModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class Person : BaseModel
    {
        private string _name;
        private int _age;

        public Person(string name, int age)
        {
            _name = name;
            _age = age;
        }
        
        public string Name { get => _name; set { _name = value; OnPropertyChanged(nameof(Name)); } }

        public int Age { get => _age; set { _age = value; OnPropertyChanged(nameof(Age)); } }
    }

    public interface IGroup<T>
    {
        bool AllTheSome { get; }
        string Text { set; get; }
    }

    public class Group<T> : BaseModel, IGroup<T>
    {

        private readonly Func<T, string> _getValue;
        private readonly Action<T, string> _setValue;
        private readonly IEnumerable<T> _items;


        public Group(IEnumerable<T> items, Func<T, string> get, Action<T, string> set)
        {
            _items = items;
            _getValue = get;
            _setValue = set;

            GetValue();
        }

        private bool _allTheSome;
        public bool AllTheSome
        {
            private set
            {
                _allTheSome = value;
                OnPropertyChanged(nameof(AllTheSome));
            }
            get
            {
                return _allTheSome;
            }
        }

        private string _text;

        public string Text
        {
            get => _text;
            set
            {
                _text = value;
                SetValue(value);
                OnPropertyChanged(nameof(Text));
            }
        }

        private void GetValue()
        {
            var firstItem = _items.FirstOrDefault();
            if (firstItem != null)
            {
                var firstValue = _getValue(firstItem);
                AllTheSome = _items.All(p => string.Equals(_getValue(p), firstValue, StringComparison.Ordinal));

                if (AllTheSome)
                {
                    _text = firstValue;
                }
            }
            else
            {
                _text = null;
            }

            OnPropertyChanged(nameof(Text));
        }

        private void SetValue(string value)
        {
            foreach (var i in _items)
            {
                _setValue(i, value);
            }
        }
    }


    public class MainModel : BaseModel
    {
        private readonly Func<Person, string> _getName = p => p.Name;
        private readonly Action<Person, string> _setName = (p, v) => p.Name = v;
        private readonly Func<Person, string> _getAge = p => p.Age.ToString();
        private readonly Action<Person, string> _setAge = (p, v) => p.Age = Convert.ToInt32(v);
        private Group<Person> _names;
        private Group<Person> _ages;

        public List<Person> Persones { set; get; }

        public MainModel()
        {
            Persones = new List<Person>
            {
                new Person("User 1", 1),
                new Person("User 2", 2),
                new Person("User 2", 3),
                new Person("User 2", 4),
                new Person("User 3", 4),
                new Person("User 4", 4),
                new Person("User 5", 5)
            };
        }

        public Group<Person> Names { get => _names; private set { _names = value; OnPropertyChanged(nameof(Names)); } }
        public Group<Person> Ages { get => _ages; private set { _ages = value; OnPropertyChanged(nameof(Ages)); } }

        private ICommand _selctionChangedCommand;
        public ICommand SelctionChangedCommand { get => _selctionChangedCommand ?? (_selctionChangedCommand = new ActionCommand<IEnumerable>(SelectonChanged)); }

        private void SelectonChanged(IEnumerable items)
        {
            var persones = items.Cast<Person>();
            Names = new Group<Person>(persones, _getName, _setName);
            Ages = new Group<Person>(persones, _getAge, _setAge);
        }
    }

    public class ActionCommand<T> : ICommand
    {
        public event EventHandler CanExecuteChanged;

        private readonly Action<T> _action;

        public ActionCommand(Action<T> action)
        {
            _action = action;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            _action.Invoke((T)parameter);
        }
    }

}


<Window x:Class="WpfApp1.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:WpfApp1"
        xmlns:view="clr-namespace:WpfApp1.View"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainModel/>
    </Window.DataContext>
    <Window.Resources>
        <Style TargetType="{x:Type ListBox}">
            <Setter Property="SelectionMode" Value="Multiple" />
        </Style>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Margin" Value="3,3,3,0" />
        </Style>
  
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox Grid.Column="0" ItemsSource="{Binding Persones}" view:SelectedChangedNotify.Command="{Binding SelctionChangedCommand}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="{x:Type local:Person}">
                    <TextBlock>
                        <TextBlock.Inlines>
                            <Run Text="{Binding Name}" /> ,
                            <Run Text="{Binding Age}" />
                        </TextBlock.Inlines>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <StackPanel Grid.Column="1" >
            <TextBox Text="{Binding Names.Text}"/>
            <TextBox Text="{Binding Ages.Text}"/>
        </StackPanel>

    </Grid>
</Window>


using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfApp1.View
{
    public static class SelectedChangedNotify
    {
        public static ICommand GetCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CommandProperty);
        }

        public static void SetCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for Command.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(SelectedChangedNotify), new PropertyMetadata(null, OnPropertyChanged));

        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is ListBox listBox)
            {
                listBox.SelectionChanged += ListBox_SelectionChanged;
            }
        }

        private static void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sender is ListBox listBox)
            {
                var command = GetCommand(listBox);
                command.Execute(listBox.SelectedItems);
            }
        }
    }

}
10 мар 18, 20:44    [21247210]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
Roman Mejtes,
Я фигею. Это столько кода для контрола?
Каждый раз пишут?
10 мар 18, 20:54    [21247216]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4030
Petro123,

очевидно, что это пример в который входит тестовая модель, всякие вспомогательные классы и прочее, что по факту уже будет, если работаешь с WPF постоянно, все это я из пальца только что высосал, ActionCommand или RelayCommand и связывание событий лучше взять из существующих сборок для шаблона MVVM, типа базовых моделей, команд и много другого. Да и пример кривенький )
10 мар 18, 21:02    [21247220]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
fgarfield
но для WinForms тоже буду рад.
вот это имхо странно.
Под винФормс все стандартное в панели компонентов находится.
Под wpf совершенно другой подход.
Как тогда вам все равно на какой технологии решение?
10 мар 18, 21:03    [21247222]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
Roman Mejtes,
Спасибо. Ок.
Честно, я пока не врубился что вообще надо)))
10 мар 18, 21:05    [21247226]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4030
Petro123,

вы сильно преувеличивайте, в реальных условиях в WPF У меня есть готовые комбики с мультиселектом и деревом, я их подключаю и делаю таким внешний вид, который подходит для текущего приложения. Конечно, готового решения нет, если самому делать лень, покупайте )
не помню, чтоб в WF был комбик аналогичный тому, про который я упомянул выше, но не уверен, не работаю с WF
10 мар 18, 21:07    [21247228]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
Roman Mejtes,
Мне интересен сабж т.к. у нас библиотека телерик для WPF.
И придётся скоро выбирать между вашим методом(своя lib) и готовым там.
Для этого нужно знать: "А что нужно ТСу"????
- что за аналогичный комбик? Мультиселект? Дерево тут причём?
...
Т.е. автор ищет комбоБокс с мультиселектом?
Картинка с другого сайта.
10 мар 18, 21:54    [21247269]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 21940
Автор внятно сказал, что хочет ввести значение в текстбокс и оно должно записаться в поле во всех строках некой выборки. Причем тут мультиселект?
10 мар 18, 22:05    [21247282]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
Shocker.Pro
Автор внятно сказал, что хочет ввести значение в текстбокс и оно должно записаться в поле во всех строках некой выборки. Причем тут мультиселект?

я внятно спрашиваю:
- это стандартный подход? Контрол?
Если да, то скрин плиз.
А накодировать я могу всё что угодно под заказ.
10 мар 18, 22:26    [21247309]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Shocker.Pro
Свой ValueConverter, который выполняет агрегацию любым удобным способом.

Вы имеете ввиду IValueConverter, метод ConvertBack ? Насколько я понял, этот метод использует 1 параметр, а вопрос именно в том, как привязать/применить это одно значение к нескольким записям

Petro123
fgarfield
но для WinForms тоже буду рад.
вот это имхо странно.
Под винФормс все стандартное в панели компонентов находится.
Под wpf совершенно другой подход.
Как тогда вам все равно на какой технологии решение?

Я совсем новичок в WPF, в то время как в WinForms более менее ориентируюсь. Хотелось начать разработку нового приложения именно в WPF. На я имел ввиду, что если кто-то поможет с WinForms, возможно, я подумаю, чтобы не выпендриваться и сделать его в старой доброй WinForms.:)

Roman Mejtes, Спасибо, постараюсь попробовать разобраться в Вашем коде...
10 мар 18, 22:42    [21247318]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 21940
fgarfield
Вы имеете ввиду IValueConverter, метод ConvertBack ? Насколько я понял, этот метод использует 1 параметр, а вопрос именно в том, как привязать/применить это одно значение к нескольким записям
Я имею ввиду конвертор в обе стороны. А привязываться надо не к каждой отдельной записи, а к свойству, представляющему набор записей. Впрочем, курите код Романа, там просто само свойство модели обеспечивает нужный функционал без конвертера.

+ Роман
прокомментируешь как-нить подход 21241155? Может я не туда поехал?
10 мар 18, 22:56    [21247337]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
fgarfield
Я совсем новичок в WPF, в то время как в WinForms более менее ориентируюсь. Хотелось начать разработку нового приложения именно в WPF. На я имел ввиду, что если кто-то поможет с WinForms, возможно, я подумаю, чтобы не выпендриваться и сделать его в старой доброй WinForms.:)

Я тоже в десктопе и бд ориентируюсь.
Трудно скрин привести?
автор
Наверняка, это распространенная задача (я часто встречал такие элементы в разном софте).

Где они?
10 мар 18, 23:09    [21247348]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Petro123
Трудно скрин привести?


Ну вот, например, панель свойств в любом CAD-е. На скрине Панель свойств Altium Designer. Внизу написано, что выбрано 53 элемента. Значение параметра Layer у них всех одинаковое, а например, параметр Х1 отличается хотя бы у одного из них, поэтому там нет значения. Если ввести в Х1 значение, оно применится ко всем 53 элементам.

К сообщению приложен файл. Размер - 19Kb
11 мар 18, 10:08    [21247570]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
fgarfield,
Теперь понятно)
Property Grid или вертикальный грид такие штуки называются.
Да, если готового типа телерика нет, то руками много кода.

К сообщению приложен файл. Размер - 69Kb
11 мар 18, 10:43    [21247582]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4030
Petro123,

платить за такую фигню?
11 мар 18, 15:17    [21247820]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
fgarfield
Member

Откуда:
Сообщений: 20
Petro123,

Спасибо за наводку! Попробую изучить
11 мар 18, 19:01    [21248021]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
Roman Mejtes,
Виртуал грид руками, докирование руками, вертикальный руками...
Работодатель решил заплатить).
11 мар 18, 21:44    [21248160]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4030
Petro123
Roman Mejtes,
Виртуал грид руками, докирование руками, вертикальный руками...
Работодатель решил заплатить).


тут все делается через стандартную панель виртуализации, нужно просто наделать кучу шаблонов для разных типов данных, что самое приятное в WPF, это то, что добавлять новые будет на много проще. докирование конкретно к контролу отношение не имеет, за это отвечают контейнеры , что такое вертикальный я не понял, скролинг? вроде всё это идет из коробки.
все что нужно сделать, это шаблон и регулировку ширины колонки руками + иерархию или группы, сортировка, фильтрация все есть.
думаю легко сделать дня за 3 основательно и не платить деньги =)
уже делал их и не 1 раз, там всё банально и просто.
11 мар 18, 22:04    [21248175]     Ответить | Цитировать Сообщить модератору
 Re: 1 элемент управления для нескольких строк  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 38640
Roman Mejtes
тут все делается через стандартную панель виртуализации, нужно просто наделать кучу шаблонов для разных типов данных, что самое приятное в WPF, это то, что добавлять новые будет на много проще.

Не могу привыкнуть.
Мне как то больше по душе понятие компонент.
Если дельфи, то это пакет файл dpk. Если шарп, то это dll и визуальный контрол в палитре.
Тут в wpf с понятием шаблон как то разбросано всё. Но это имхо. Могу ошибаться.
...
Докирование это в телерике бросить контрол типа панели материнской куда и будет все прилипать докироваться.
...
Вертикальный это этот сабж. Разный тип не в колонках, а строках.
...
Да. Мне интересен ваш опыт. Видно что вы практик.
12 мар 18, 07:28    [21248402]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить