Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
1

Задача на размышление (приведение типов или, может, другое решение)

09.11.2013, 13:16. Показов 939. Ответов 14
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть класс MasterPanel, одним из элементов которого является панель Panel. Элементы MasterPanel хранятся в словаре Dictionary<string, MasterPanel>.
Доступ к панели через MasterPanel.Panel. Панели содержат на себе различные контролы Control (от конкретного типа контрола код зависеть не должен). Прямого доступа к элементам на панели нет. Только доступ к самой панели.
Требуется с этих нескольких панелей считать значения в элементах и записать их в одну коллекцию, xml-файл или что-то другое, что потом позволит восстановить значения.
Я мало до чего додумался.
Есть идея записать все значения из panel.Controls (для каждой панели) в коллекцию List<var>.
Тут возникает несколько проблем:
1. Не во всех контролах значение записывается в свойство text. А value Или selectedItem из Control не достать, требуется приведение.
2. Если какой-либо контрол, например, Label взять из panel.Controls (без приведения он будет иметь тип Control), и поместить его самого в var, то какой тип получит эта переменная var, и что делать дальше.

Помогите, пожалуйста с решением проблемы.

Прилагаю описание класса MasterPanel:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
        /// <remark>
    /// Класс панели мастера
    /// </remark>
    public class MasterPanel
    {
        private string nextPanel = null;
        private Panel panel;
        private bool canContinue = false;
        
        #region СВОЙСТВА
        /// <summary>
        /// Возвращает элемент Control представляющий панель для ее указания как родителя
        /// </summary>
        public Control Panel {
            get { return panel; }
        }
        
        /// <summary>
        /// Задает родительский контейнер для панели
        /// </summary>
        public Control parent {
            set {panel.Parent = value; }
        } 
        
        /// <summary>
        /// Задает положение панели в родительском контейнере
        /// </summary>
        public Point Location {
            set {panel.Location = value; }
        }   
        
        /// <summary>
        /// Возвращает или задает ключ для получения следующей панели настройки
        /// </summary>
        public string NextPanel {
            get { return nextPanel; }
            set { nextPanel = value; }
        }
        #endregion      
        
        public MasterPanel()
        {
            this.panel = new Panel();
            panel.Size = new System.Drawing.Size(400,340);
            panel.AutoScroll = true;
            panel.AutoSize = false;
        }
        
        /// <summary>
        /// Отображает панель в родительском контейнере
        /// </summary>
        public void Show()
        {
            if(panel.Parent != null) panel.Show();
            else throw new Exception("Не указан родительский контейнер!");
        }
        
        public void Hide()
        {
            panel.Hide();
        }
    }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.11.2013, 13:16
Ответы с готовыми решениями:

Нюанс с dynamic_cast: может ли указанное приведение типов быть корректным?
Может ли такое приведение типов (второй dynamic_cast) быть корректным?:class A {public: virtual...

конвертирование или приведение типов
есть две переменные типа object, мне нужно: -одну преобразовать в тип OperationRequest, -другую...

Неправильное приведение типов или как?
Короче вот код void CMyDialog::OnBnClickedButtonEdit() { double number ; CString t; number=...

Приведение типов. Char к String или на оборот?
Всем привет. Проблема в приведении типов, ну мне так кажется. Нужно Именно по char проверить нет...

14
Неадекват
1492 / 1230 / 246
Регистрация: 02.04.2010
Сообщений: 2,789
09.11.2013, 14:15 2
Может быть стоит описать что вы хотите получить, а не просто реализацию непонятно чего?
1
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
09.11.2013, 16:36  [ТС] 3
Что-то вроде мастера (wizard) для получения некоторых настроек. ПО нажатию кнопки "Далее" мы берем из MasterPanel ключ, указывающий на следующую панель и отображаем ее вместо текущей.
Этот мастер выполняется в виде отдельной библиотеки. Панели описываются в программе. Поэтому надо, чтобы контролы добавлялись на панель в программе и код работы мастера не зависел от того, какие контролы будут размещены на панелях.
Таким образом, в коде мастера есть коллекция-словарь для панелей.
Чтобы получить требуемый конечный результат, мы последовательно создаем различные MasterPanel и добавляем их в эту коллекцию, указывая их ключи.
Таким образом этот мастер можно использовать в различных ситуациях и различных программах, просто заменяя панели.
У меня получилось описать все, кроме главного - получения введенных (указанных) значений из контролов на панелях.
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.11.2013, 17:32 4
fadeinmad, у меня был похожий код, который на одной и той же форме генерировал контролы, в зависимости от переданного класса. Если надо, могу позже выложить
1
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
09.11.2013, 17:35  [ТС] 5
Да мне просто бы совет, как можно значения брать. Я не ищу готового решения, мне хотя бы намек =)
Просто не могу найти приемлемого способа, чтобы сделать эту библиотеку с формой мастера универсальной.
Мне в нескольких программах требуется, точнее, судя по проектам, потребуется мастер. И везде мастера разные, точнее, контролы в них. Хотелось бы знать, можно ли каким-то образом считывать значения из них единым способом?
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.11.2013, 17:38 6
fadeinmad, я рефлексией проходил по всем открытым полям/свойствам, для каждого текстового поля генерировал текстбоксы, для числовых - numericUpDown, для булевских значений - CheckBox'ы, для полей из сложных классов - рекурсивно вызывать эту же функцию для создания панельки, на которой по схеме выше разместить нужные контролы.
1
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
09.11.2013, 20:05  [ТС] 7
Цитата Сообщение от Psilon Посмотреть сообщение
для каждого текстового поля генерировал текстбоксы, для числовых - numericUpDown, для булевских значений - CheckBox'ы, для полей из сложных классов - рекурсивно вызывать эту же функцию для создания панельки, на которой по схеме выше разместить нужные контролы.
У меня контролы уже будут, мне надо считать из них значения. То есть наоборот получить текстовые, числовые значения. Причем я не знаю, откуда я их беру, так как я знаю только тип Control.

В крайнем случае, можно запоминать сами контролы, хоть это и не очень хорошо, и может оказаться ресурсоемко очень.
Но вот как тогда, "имея на руках" тип Control, узнать тип контрола и привести его к нему, чтобы получить значение. Да и тогда анализ контролов и получение значений окажется весьма сложной процедурой (много кода и ветвлений для анализа).

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


З.Ы. Извините за такие описания невнятные. Сложно объяснить, чего требуется, так как сам не совсем до конца понимаю.
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.11.2013, 20:08 8
C#
1
2
3
4
5
6
7
8
[nick]fadeinmad[/nick], ну так можно тупо
public string GetValueFromControl(Control control)
{
   if (control is TextBox)
      //
   else if (control is NumericUpDown)
      //...
}
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
09.11.2013, 20:09  [ТС] 9
Тогда уж и через switch можно прописать.
Но это глуповато выходит((...
Я думал в xml файл все выводить, но это, в принципе, тоже выход не ахти. =)
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.11.2013, 20:16 10
Пример:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Text = "Hello";
            numericUpDown1.Value = 100;
            checkBox1.Checked = true;
            button1.Click += (o, args) => AnalyzeIt(textBox1);
            button2.Click += (o, args) => AnalyzeIt(numericUpDown1);
            button3.Click += (o, args) => AnalyzeIt(checkBox1);
        }
 
        public void AnalyzeIt(Control control)
        {
            const BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase;
            string propName;
            if (control is TextBox)
                propName = "Text";
            else if (control is NumericUpDown)
                propName = "Value";
            else if (control is CheckBox)
                propName = "Checked";
            else 
                throw new ArgumentException();
            var prop = control.GetType().GetProperty(propName, bf);
            object obj = prop.GetValue(control);
            MessageBox.Show(obj.ToString());
        }
1
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
09.11.2013, 20:30  [ТС] 11
Интересный способ, не знал про такой. Спасибо, большое. Буду пробовать =)
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.11.2013, 20:50 12
fadeinmad, можно короче (и не париться с ветками if else if...)
C#
1
2
3
4
5
6
7
8
9
            public void AnalyzeIt(Control control)
            {
                const BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase;
                string[] propNames = {"Text", "Value", "Checked"};
                var props = control.GetType().GetProperties(bf);
                var prop = props.First(x => propNames.Contains(x.Name));
                object obj = prop.GetValue(control);
                MessageBox.Show(obj.ToString());
            }
достаточно в массив забить список нужных свойств.
1
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
09.11.2013, 21:00  [ТС] 13
Неплохо)) Думаю, как раз что-то типо этого буду использовать =)
0
9 / 9 / 2
Регистрация: 25.11.2012
Сообщений: 115
10.11.2013, 09:05  [ТС] 14
Цитата Сообщение от Psilon Посмотреть сообщение
C#
1
2
3
4
5
6
7
8
9
            public void AnalyzeIt(Control control)
            {
                const BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase;
                string[] propNames = {"Text", "Value", "Checked"};
                var props = control.GetType().GetProperties(bf);
                var prop = props.First(x => propNames.Contains(x.Name));
                object obj = prop.GetValue(control);
                MessageBox.Show(obj.ToString());
            }
Обнаружил небольшой недочет. Свойство Text есть у всех контролов и, естественно, оно будет выбираться всегда.
вместо
C#
1
2
3
string[] propNames = {"Text", "Value", "Checked"};
var props = control.GetType().GetProperties(bf);
var prop = props.First(x => propNames.Contains(x.Name));
стоит написать

C#
1
2
3
4
5
string[] propNames = {"Value", "Checked"};
var props = control.GetType().GetProperties(bf);
var prop;
try {prop = props.First(x => propNames.Contains(x.Name));}
catch {prop = props.First(x => x.Name == "Text");}
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
10.11.2013, 11:10 15
fadeinmad, просто напиши text последним....
0
10.11.2013, 11:10
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.11.2013, 11:10
Помогаю со студенческими работами здесь

Что быстрее будет работать сравнение или (сложение и приведение типов)?
Эти строчки if(h == 0xffffffff) { code_1 } else { code_2 } или if(h + 1) { code_2 } else...

Фреймы или может что-то другое
Здравствуйте. Вообщем не знаю как правильно сделать. Есть выпадающий список в нем значения:...

Не требуется приведение типов при умножении типов Byte
Читал тут книгу(Г. Шилдт, &quot;Полный справочник по C#&quot;), и нашел такое (ст. 77) Поскольку при...

Решена задача(как я полагаю :D), но хочется другое решение
Ввести последовательность S и вывести второй максимум этой последовательности, т. е. элемент...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru