С Новым годом! Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.72/18: Рейтинг темы: голосов - 18, средняя оценка - 4.72
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
1
WPF

Установка Control.Style не триггерит set функционал у свойства класса

21.05.2019, 12:59. Показов 3281. Ответов 33

Author24 — интернет-сервис помощи студентам
Всем привет.

У меня есть класс - CoordinateView (клеточка). Он экстендит класс Grid. Также в нём есть два поля - TextBlock и Rectangle. Они добавлены в этот класс как его Children. Первый преднозначен для того чтобы показывать текст, другой нужен чтобы устанавливать цвет и толщину рамок . То есть, задача этой структуры - иметь рамки, цвет и текст. (Если есть такой control по дефолту, дайте знать, я не нашёл, и сделал вот Grid с TextBlock и Rectangle в качестве его "детей", но вопрос пока не в этом).

Далее, я хочу установить свойства этой моей клеточке. Всякие разные, один из которых, например, Margin. Но хочу это делать динамично. Поэтому использую свойство Style и создаю объект из вне и добавляю в него Setter'ы того, что мне нужно. И всё работает. Всё, чётенько и классненько. Почти.

В основном свойства, которые я устанавливаю относятся именно к классу Grid. Но вот есть несколько значений свойств, которые мне нужно передать "детям" (TextBlock и Rectangle), например Label и StrokeThickness. Эти два поля у меня приватные, я не хочу из вне чтобы был доступ к ним. Поэтому я создал wrapping свойства в классе своей клеточки в которых устанавливаю значения "детям". Получается вот так:
C#
1
2
3
4
5
public Brush Stroke
{
    get => rectangle.Stroke;
    set => rectangle.Stroke = value;
}
Проблема заключается в том, что, когда я устанавливаю значения этим своим свойствам (конечно, я создал DependencyProperty к каждому из этих свойств чтобы Style.Setter мог им пользоваться), то значение не передаётся дальше в rectangle.Stroke. Я установил breakpoint на строке set => ... и когда программа проходит код coordinateView.Style = style, то код не останавливается на этом brealpoint'е. Мне это не нравится, потому что значение Stroke моей клеточки устанавливается (я вижу в debugging окне изменение значения), а вот set => ... не тригеррится и поэтому rectangle.Stroke не получает нового значения.

Вопрос: как сделать так, чтобы rectangle.Stroke всё-таки получал это значение, когда я устанавливаю стиль моей клеточки.


Заранее спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.05.2019, 12:59
Ответы с готовыми решениями:

Работа свойства Bottom класса Control
Объясните пожалуйста, как с помощью свойства Bottom (которое получает расстояние (в пикселях) между...

Выполнить команду в set свойства для свойства SelectedItem (ComboBox ) MVVM
Хай Коротко: при каждом выборе элемента из ComboBox нужно выполнять команду, для которой в...

Как дополнить функционал класса из другого класса
Вот допустим, написал я класс TMatrix (матрица), можно добавлять строки, столбцы, есть capacity и...

Свойства get и set
Можно ли изменить тип возвращаемого значения через свойства? Или же свойства не приспособлены к...

33
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
21.05.2019, 13:37 2
Лучший ответ Сообщение было отмечено Элд Хасп как решение

Решение

Цитата Сообщение от Pro100Tom Посмотреть сообщение
делал вот Grid с TextBlock и Rectangle в качестве его "детей"
Какой-то сложный вариант Вы выбрали.
А такая реализация UC Вам не подойдёт?

CB
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    /// <summary>Логика взаимодействия для BorderTextBlock.xaml</summary>
    public partial class BorderTextBlock : Border
    {
        public BorderTextBlock()
        {
            InitializeComponent();
        }
 
 
 
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(BorderTextBlock), new PropertyMetadata(null));
 
 
    }
XAML
XML
1
2
3
4
5
6
7
8
9
10
<Border x:Class="WPF1903.BorderTextBlock"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPF1903"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <TextBlock Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:BorderTextBlock}}}"/>
</Border>
1
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
21.05.2019, 14:01  [ТС] 3
Блин, круто! Идея ясна. Мне стоит поизучать XAML, а то я им пренебрегаю ввиду незнания.

Хорошо, я полагаю будет значение передаваться в TextBlock, когда мы будем устанавливать значение Text в borderTextBlock. А будет ли это работать (смогу вечером протестировать только), если сделаю borderTextBlock.Style = style, если в style будет Setter с TextProperty? У меня проблема именно в этом.
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
21.05.2019, 14:14 4
Цитата Сообщение от Pro100Tom Посмотреть сообщение
А будет ли это работать (смогу вечером протестировать только), если сделаю borderTextBlock.Style = style, если в style будет Setter с TextProperty?
Не понял, что Вы хотите сделать.
При использовании UC в View Вы хотите в стиле этого UC обратиться к его свойству Text (которое было добавлено)?
Если да, то работать будет без каких либо проблем.

Цитата Сообщение от Pro100Tom Посмотреть сообщение
Идея ясна. Мне стоит поизучать XAML, а то я им пренебрегаю ввиду незнания.
Изучать XAML нужно ОБЯЗАТЕЛЬНО. Это основной язык для создания WPF View. Только когда его возможностей не хватает, стоит использовать другие языки (в основном C#).

Но то что сделано в XAML полностью можно повторить и в CB на C#. Суть в другом. Вы обращаетесь DP-свойствами как с CLR-свойствами. А в данном случае вместо
C#
1
2
3
4
5
public Brush Stroke
{
    get => rectangle.Stroke;
    set => rectangle.Stroke = value;
}
Надо устанавливать привязку. Без разницы где - в XAML или в CB на C#.
Мне проще это сделать в XAML - там конструктор сам создаёт привязки. Просто выбираешь где, какую привязку надо сделать, а весь код вставляет конструктор. В CB это всё надо делать "ручками".
1
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
21.05.2019, 14:20  [ТС] 5
Всё понял. Буду изучать (С WPF играюсь чисто для себя, поэтому чайник на данный момент). Вечером реализую и отпишусь. А пока что большое спасибо Вам.

P. S. не по теме, но может быть Вы могли бы порекомендовать литературу по WPF c XAML? Я, конечно, могу выбрать вслепую, но мне интересно Ваше мнение.
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
21.05.2019, 14:48 6
Лучший ответ Сообщение было отмечено Элд Хасп как решение

Решение

Цитата Сообщение от Pro100Tom Посмотреть сообщение
Всё понял. Буду изучать
Тоже самое но чисто в на C#.
Не тестировал - возможно есть ошибки.
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 /*partial*/ class BorderTextBlock : Border
    {
        public BorderTextBlock()
        {
            //InitializeComponent();
 
            TextBlock textBlock = new TextBlock();
            Child = textBlock;
            Binding bindText = new Binding();
            RelativeSource relative = new RelativeSource();
            relative.AncestorType = typeof(BorderTextBlock);
            bindText.RelativeSource = relative;
            PropertyPath path = new PropertyPath(nameof(TextProperty));
            bindText.Path = path;
            bindText.Mode = BindingMode.OneWay;
            textBlock.SetBinding(TextBlock.TextProperty, bindText);
        }
 
 
 
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(BorderTextBlock), new PropertyMetadata(null));
 
    }
Добавлено через 3 минуты
Цитата Сообщение от Pro100Tom Посмотреть сообщение
но может быть Вы могли бы порекомендовать литературу по WPF c XAML
Книги ни какие не читал.
В основном читал web ресурсы: METANIT, professorWeb, документацию doc.microsoft. Совсем в самом начале сморел несколько курсов по YouTube.
1
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
21.05.2019, 23:49  [ТС] 7
Работает! Спасибо большое! Я счастлив
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
27.05.2019, 22:46  [ТС] 8
Элд Хасп,

Привет ещё разочек. У меня возникла ещё одна проблемка. Думал, создать новую тему, но тема всё-таки остаётся той же, поэтому пишу сюда.

Проблема заключается в том, что binding не работает. Теперь на этот раз между свойствами Style и Style классов View (CoordinateView) и View Model (CoordinateViewModel).

View:
C#
1
2
3
4
5
6
7
8
9
10
<Border x:Class="BattleshipGame.VisualComponent.Views.CoordinateView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:local="clr-namespace:BattleshipGame.VisualComponent.Views"
        mc:Ignorable="d">
    <TextBlock Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:CoordinateView}}}"
               HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Windows;
using System.Windows.Controls;
 
namespace BattleshipGame.VisualComponent.Views
{
    public partial class CoordinateView : Border
    {
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(CoordinateView));
 
        public CoordinateView()
        {
            InitializeComponent();
        }
 
        public string Text
        {
            get => GetValue(TextProperty) as string;
            set => SetValue(TextProperty, value);
        }
    }
}
ViewModel:
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
using BattleshipGame.BattlefieldComponent.Models;
using BattleshipGame.CoreComponent;
using System.Windows;
 
namespace BattleshipGame.ShipComponent.ViewModels
{
    public class CoordinateViewModel : ViewModelBase
    {
        Style style, styleIdle, styleMouseOver, styleMouseDown, currentStyle;
        Battlefield battlefield;
        Coordinate coordinate;
 
        public CoordinateViewModel()
        {
 
        }
 
        public CoordinateViewModel(Battlefield battlefield, Coordinate coordinate, Style style)
        {
            this.battlefield = battlefield;
            this.coordinate = coordinate;
            styleIdle = new Style(typeof(FrameworkElement), style);
            styleMouseOver = new Style(typeof(FrameworkElement), style);
            styleMouseDown = new Style(typeof(FrameworkElement), style);
 
            currentStyle = StyleIdle;
        }
 
        public void UpdateCurrentStyle()
        {
            Style = currentStyle;
        }
 
        public Style Style
        {
            get => style;
            set => SetProperty(ref style, value);
        }
 
        public Style StyleIdle { get; set; }
 
        public Style StyleMouseOver { get; set; }
 
        public Style StyleMouseDown { get; set; }
 
        public static readonly DependencyProperty StyleProperty =
            DependencyProperty.Register(nameof(Style), typeof(Style), typeof(CoordinateViewModel));
    }
}
Main:
C#
1
2
3
4
5
6
7
8
9
10
11
12
var coordinateViewStyle = new CoordinateViewStyle(coordinate);
                var coordinateViewModel = new CoordinateViewModel(battlefield1, coordinate, coordinateViewStyle.Style);
 
                var binding = new Binding();
                binding.Path = new PropertyPath(nameof(CoordinateViewModel.StyleProperty));
                binding.Mode = BindingMode.TwoWay;
                binding.Source = coordinateViewModel;
 
                var coordinateView = new CoordinateView();
                coordinateView.SetBinding(FrameworkElement.StyleProperty, binding);
 
                coordinateViewModel.Style = coordinateViewStyle.Style;
Не подбирает стиль, ёлки палки. Когда делаю напрямую, то всё работает:
C#
1
//coordinateView.Style = coordinateViewStyle.Style;
Base:
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
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
 
namespace BattleshipGame.CoreComponent
{
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName]string propertyName = null)
        {
            if (!EqualityComparer<T>.Default.Equals(field, newValue))
            {
                field = newValue;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 
                return true;
            }
 
            return false;
        }
    }
}
Почему binding не работает? Вроде бы всё правильно установил. С mode игрался, и с PropertyPath, и с реализацией INotifyPropertyChanged. Не могу найти проблему.
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
27.05.2019, 23:50 9
Цитата Сообщение от Pro100Tom Посмотреть сообщение
binding.Path = new PropertyPath(nameof(CoordinateViewModel.StyleProperty));
Я или что-то пропускаю..., или Вы что-то не то делаете.

Я не вижу у Вас в классе CoordinateViewModel свойства StyleProperty
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
28.05.2019, 00:01  [ТС] 10
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Я не вижу у Вас в классе CoordinateViewModel свойства StyleProperty
Ну как же так? Вот же он (под View Model проскроллить надо вниз код):
Цитата Сообщение от Pro100Tom Посмотреть сообщение
public static readonly DependencyProperty StyleProperty =
* * * * * * DependencyProperty.Register(nameof(Style), typeof(Style), typeof(CoordinateViewModel));
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
28.05.2019, 00:10 11
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Ну как же так? Вот же он (под View Model проскроллить надо вниз код):
Да, не проскролил.
Я посмотрел Вашу реализацию свойства Style и увидел, что оно реализовано как CLR свойство.
Поэтому дальше и не смотрел - это значения не имеет. Свяжите его с DependencyProperty StyleProperty.
Они должны работать как единое целое. Скорее всего дело именно в этом.

Добавлено через 2 минуты
C#
34
35
36
37
38
        public Style Style
        {
            get => (Style) GetValue(StyleProperty);
            set => SetValue(StyleProperty, value);
       }
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
28.05.2019, 00:19  [ТС] 12
Извините, но мой класс ViewModel не есть FrameworkElement. Я не могу вызвать GetValue в нём.

У меня вот какая цель. Я создал view (клеточка) и view model. Хочу их забиндить между собой. Во второй будет находиться логика, в зависимости от которой будет меняться свойство style. Всё, что мне хотелось бы, чтобы это свойство автоматом бы передавалось в мой view (клеточку).
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
28.05.2019, 00:34 13
Цитата Сообщение от Pro100Tom Посмотреть сообщение
звините, но мой класс ViewModel не есть FrameworkElement. Я не могу вызвать GetValue в нём.
Класс в котором находится DependencyProperty свойство должен наследоваться от DependencyObject. Без этого Вы не можете создать полноценное DP-свойство.

Если Вам надо привязать к CLR свойству, то в привязке и указывайте название CLR свойства.
C#
5
                binding.Path = new PropertyPath("Style");
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
28.05.2019, 00:48  [ТС] 14
В viewModelBase сделал вот так:
C#
1
2
3
4
5
protected void SetProperty<T>(DependencyProperty dp, T newValue, [CallerMemberName]string propertyName = null)
{
    SetValue(dp, newValue);
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Сам класс теперь выглядит вот так:
C#
1
public abstract class ViewModelBase : DependencyObject, INotifyPropertyChanged
В child'е сделал вот так:
C#
1
2
3
4
5
6
public Style Style
{
    get => GetValue(StyleProperty) as Style;
    //set => SetProperty(ref style, value);
    set => SetProperty(StyleProperty, value);
}
(binding.path не менял на clr) Не работает

P. S. Ещё до всего этого менял binding.path на clr всё равно не работало. Когда открыл новый проект и сделал тоже самое с полем типа string - всё работало. Может Style какой-то исключительный тип? Ну или я сам исключительный тип ввиду кривых рук.
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
28.05.2019, 00:59 15
Pro100Tom, у меня нет практики создания привязок в коде.
Кроме как в этой теме не делал ни когда.
Надо пробовать и проверять.
Вы в дебагере проверяли саму привязку? Значения после изменений?
Попробуйте в интерпретаторе создавать привязку и проверять её значение.
Реализовать в XAML.

Что Вы собственно реализуете? Что за решение? Как-то Вы через чур сложным путём идёте. Верно ли Вы выбрали путь реализации?
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
28.05.2019, 01:52  [ТС] 16
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вы в дебагере проверяли саму привязку? Значения после изменений?
Конечно, всё проверял. Говорю же, отдельный проект создал чтобы протестировать на более простом варианте. В xaml не могу реализовать, у меня там пару значений в стиле должны быть высчитаны в run-time.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Что Вы собственно реализуете?
Смотрите, пишу игру battleship. Есть клеточки, у каждой свой стиль. Если мы наводим мышкой, то меняем цвет. Если жмём по клеточке, снова меняем цвет. Когда произошёл клик, хочу содать command, который тригеррил бы функцию в соответствующей view model, там будет происходить логика мол есть ли на поле боя корабль в этой клетке. Если есть, то устанавливаем стиль себе (во view model), а этот стиль автоматом забиндин будет с полем стиля самой клеточки. Например, если на этой клетке есть корабль, то после клика, она меняет цвет.

Добавлено через 41 минуту
Разобрался. Там была проблема не в биндинге, а в свойстве класса стиля. Сорри за винегрет, всё работает.
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
28.05.2019, 10:52 17
Цитата Сообщение от Pro100Tom Посмотреть сообщение
Разобрался. Там была проблема не в биндинге, а в свойстве класса стиля. Сорри за винегрет, всё работает.
Если можете покажите и объясните решение.

Цитата Сообщение от Pro100Tom Посмотреть сообщение
Смотрите, пишу игру battleship.
На мой взгляд у Вас путаница между данными и их отображением.
То как Вы делаете, ещё допустимо для какого-то графического редактора, где отображение самих элементов и является источником данных.
Но для морского боя..... Данные здесь - это чисто CLR классы. Зачем здесь все эти манипуляции...
Очень большая вероятность, что Вы неверно спроектировали приложение, отсюда и такие неспецифические для WPF проблемы.

Прочитайте Морской бой
В теме я начал проектировать Морской Бой, но TC перестал отвечать - поэтому не завершил.
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
28.05.2019, 19:55  [ТС] 18
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Если можете покажите и объясните решение.
На самом деле, я толком не разобрался почему та реализация вызывала именно такой результат. Я погляжу еще вечерком, как дома буду. Но я там быстренько просто в конструктере класса стиля создаю стили и кидаю их в его свойство, а потом уже присваиваю его свойство свойству моей viewModel. Так не работало, но зато заработало, когда я не использовал никаких свойств в своём классе стиля и просто создал функцию, в которой возвращается новый экземпляр класса Style, тогда всё заработало. Естественно я всё почищу ибо как раз пишу эту игру для того чтобы поиграться именно с архитектурой.

Вообще для меня архитектура важна сильнее всего. Я работаю в eCommerce и ненароком знаю о важности extensibility и flexibility в коде, а так же reusability.

Поэтому я реально ломаю голову по поводу решения. Я не тупо выбираю архитектуру по книгам, а вырисовываю решения в голове потенциальных проблем. Поэтому, когда Вы мне говорите, что я нагромождаю, то мне хотелось бы услышать Вашу альтернативу.

Смотрите. С чем мне связать стиль класса coordinateView? С моделью координаты не могу. Она имеет только поля row и column. Я не хочу добавлять туда поля типа hasShip, wasChecked потому что эти вещички добавляют зависимость от других классов.

Может связать клеточку с моделью корабля? Ведь, если корабль был ранен или убит, мы сможем понять, что цвет клеточки должен изменяться. Но а где мне тогда доставать нужный сет стилей для клеточки, корабль на которой был подбит? И ещё, если несколько клеточек связаны с одним кораблем, то я уже не могу изменить одну из этих клеточек отдельно, если свойство корабля изменится, а это минус.

Я вообще не хотел использовать биндинги. Я выбрал WPF потому что у него крутые controls. А язык выбрал потому что просто люблю C# и окна. Хотя лабиринт я пишу на C++ и 3D графику тоже писал на C++. Так вот, я тут понюхал про viewModels и понял, в чём заключается их принцип (наверное). Я связываю этот viewModel с coordinateView и уже из viewModel использую различные сервисы (модели) которые там определяют есть ли корбаль на этоё клетки или нет, ранен ли он, если есть и в зависимости от этого результата "возвращает" нужный стиль моей клеточке, которая будет его использовать. Вообще, я хочу создать сэт стилей для каждого случая (есть корабль, ранен ли он или убит), в котором есть стили трёх states: idle, mouseOver, mouseDown. По-моему прикольно, ибо я могу менять всё что угодно, когда навожу мышку на поле врага; скажем, поменяется цвет (типа хайлайт). Нажимаю мышкой, label отображает знак вопроса, мол типа есть ли тут корабль. А если попал, то отображает крестик. Также меняется цвет и всё это по-моему здорово.

Скажите мне, как тут можно упростить и улучшить архитектуру и я с удовольствием к Вам прислушаюсь ибо пишу это всё для того чтобы стать лучше.

P. S. Книги Роберта Мартина и Dessign Patterns by Gang of Four конечно же прочитал.
В общем, заранее спасибо.

P. P. S. А вообще желательно бы было связать интерфейс класса viewModel с моей клеточкой, а потом уже иметь возможность полиморфить этот класс как угодно в различных компонентах так чтобы базовые остались стабильными.
0
Модератор
Эксперт .NET
15849 / 10995 / 2854
Регистрация: 21.04.2018
Сообщений: 32,267
Записей в блоге: 2
28.05.2019, 22:23 19
Цитата Сообщение от Pro100Tom Посмотреть сообщение
На самом деле, я толком не разобрался почему та реализация вызывала именно такой результат.
Ну, если разберётесь - напишите.
Я привязки в коде C# не создаю. Но знания лишними не бывают.

Цитата Сообщение от Pro100Tom Посмотреть сообщение
Я вообще не хотел использовать биндинги. Я выбрал WPF потому что у него крутые controls.
Привязки - это самое главное нововведение в WPF (по сравнению с WF).

Цитата Сообщение от Pro100Tom Посмотреть сообщение
Скажите мне, как тут можно упростить и улучшить архитектуру и я с удовольствием к Вам прислушаюсь ибо пишу это всё для того чтобы стать лучше.
В современном программировании принято разделять данные и их отображение.
Основным паттерном для WPF является MVVM. Фактически WPF специально под этот паттерн и создавался для реализации View (Представление).

В MVVM за обработку данных отвечает Model (Модель). Модель работает полностью независимо от других частей приложения. Её работа не зависит от того где она выполняется: на локальном компе, на сервере, на WEB сервере и т.д.
Модель ни как не связана с представлением. Представление для визуализации данных может быть любым WPF, WF, консоль и любое другое.

Вот теперь подумайте. Если View - это консоль. А обработка данных (кораблей, палуб) у Вас завязана на стиль. От куда в консоли стиль? То есть Вы фактически используете визуальные свойства элементов как данные.

Как я писал выше, такое допустимо для какого-то графического приложения. Но ни как ни для игры "Морской бой".

Примерно как начать реализацию Модели я уже Вам дал ссылку. Модель - это первое что должно быть создано в WPF приложении. View создаётся позже. У Вас же Модели, вообще, нет. Из-за этого многочисленные неспецифические проблемы.

Если делать нормально (то есть сначала Model, потом View и напоследок ViewModel), то я думаю Ваше приложение можно сделать за несколько часов.

MVVM - Это ни какой-то "заговор" программистов. Это паттерн придуманный для значительного облегчения создания приложения. Так как он используется практически всеми, то код приложения становится читаемым, шаблонным, понятным. Соответственно для такого кода есть множество шаблонных решений.

Можно ли создавать WPF приложения вне MVVM? Это подобно "удалению гланд через задницу". Конечно, можно. Но это очень трудно. ОЧЕНЬ - это в десятки раз.

Здесь в разделе есть несколько тем где я показывал как шаг за шагом надо реализовывать WPF приложение.
Хотите научить - по возможности помогу. Прочитайте темы в разделе
Готовые решения, примеры и рекомендации начинающим на WPF [Элд Хасп]
Склейщик фото (создание MVVM приложения)
Суммирование элементов в 2048

Что не понятно интересуйтесь прямо в темах.
Когда разберётесь - можно так же шаг за шагом реализовать и Ваше приложение.
0
154 / 31 / 11
Регистрация: 29.10.2012
Сообщений: 397
29.05.2019, 00:53  [ТС] 20
Спасибо за ответ и да, я знаю о ролях этих компонентов.

У меня вопрос по следующему комментарию:
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вот теперь подумайте. Если View - это консоль. А обработка данных (кораблей, палуб) у Вас завязана на стиль. От куда в консоли стиль? То есть Вы фактически используете визуальные свойства элементов как данные.
У меня есть модель. Она возвращает (во viewModel) мне значение (мимо, ранил, убил), и тот уже "высылает" (биндингом) нужный стиль для моей клеточки. Тут Вы говорите про консоль как вид, чтобы я подумал про разделение. Правильно ли я понимаю, что для каждого вида нужен свой viewModel? Если так, то я не вижу ошибки в своей архитектуре. Мы создаём консоль, создаем viewModel для неё и вызываем ту же модель, которая возвращает "мимо/ранил/убил" и viewModel уже решает что там надо возвращать окну. Что в моей реализации не так-то?

MVC, (теперь и чуть-чуть MVVM) мне знакомы, и я хорошо понимаю, что касается модели, а что нет, ибо в данном случае как раз после промаха игрока пойдёт выстрел AI, а ему вид вообще не нужен.

За литературу спасибо, я обязательно всё изучу. И начну вот в поезде на работу завтра.
0
29.05.2019, 00:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.05.2019, 00:53
Помогаю со студенческими работами здесь

свойства get;set;
Доброе время суток, решил на досуге почитать тут про лямбда выражения и с ужасом для себя открыл,...

Свойства set get
Написал код с использованием свойств, но они не используються( Тоесть они вроде есть, но смысла от...

Свойства get set
Доброй ночи. public class Date { private int month = 7; public int Month ...

Биндинг свойства контрола к одной из переменных свойства класса
Добрый день. У меня есть вопрос по биндингу. Ситуация следующая: У меня есть структура, ...


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

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