powered by simpleCommunicator - 2.0.40     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Привязка координат элемента в Canvas
25 сообщений из 29, страница 1 из 2
Привязка координат элемента в Canvas
    #39727653
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте, я недавно начал изучать WPF и столкнулся с проблемой. Я пытался привязать(забиндить) координаты элемента, который находится в Canvas:

Код: xml
1.
2.
3.
<Canvas Name="Canvas">
    <Rectangle Fill="Black" Width="60" Height="60" Canvas.Left="{Binding X, Mode=OneWay}" Canvas.Top="{Binding Y, Mode=OneWay}"/>
</Canvas>



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
namespace WpfApp7
{
    public partial class MainWindow : Window
    {
        public double X { get; set; }
        public double Y { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            X = 111;
            Y = 111;
        }
    }
}



Однако это не возымело никакого эффекта. При этом, если менять свойства Canvas.Top и Canvas.Left вручную, то квадрат меняет своё расположение в редакторе. Я пробовал ставить Mode TwoWay и даже использовать интерфейс INotifyPropertyChanged, который применяется в патерне MVVM, но ничего из этого не помогло. У меня складывается такое ощущения, что если это заработает-свершится настоящее чудо. Скажите, пожалуйста, что я делаю не так.
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727661
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Canvas.Left="{Binding X, Mode=OneWay}" Canvas.Top="{Binding Y, Mode=OneWay}"
неправильный Binding, Вы делайте связывание с контекстом, а не с окном. В контексте нет полей X и Y
Они есть в классе окна. Либо используйте ElementName связывание и задайте имя окну, либо используйте RelativeSource связывание
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727662
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: xml
1.
2.
3.
4.
5.
<Canvas Name="Canvas">
    <Rectangle Fill="Black" Width="60" Height="60" 
               Canvas.Left="{Binding X, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}" 
               Canvas.Top="{Binding Y, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}"/>
</Canvas>


вот рабочий вариант вашего примера
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727673
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за быстрый ответ.
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727683
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хотя нет, знаете что? Спасибо вам ОГРОМНОЕ. На других сайтах люди даже особо не смотрели на мой код и отмахивались этим шаблонным: нужен интерфейс INotifyPropertyChanged и тому подобное. А вы действительно мне помогли. Буду почаще заходить на этот сайт)
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727716
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
111DarkFox111Хотя нет, знаете что? Спасибо вам ОГРОМНОЕ. На других сайтах люди даже особо не смотрели на мой код и отмахивались этим шаблонным: нужен интерфейс INotifyPropertyChanged и тому подобное. А вы действительно мне помогли. Буду почаще заходить на этот сайт)Вы задали вопрос http://www.cyberforum.ru/wpf-silverlight/thread2345072.html#post13027693
И я Вам там ответил. В том числе дал полностью рабочий пример кода. Интерфейс INotifyPropertyChanged для свойств предназначенных для привязывания обязателен.
Вот тот пример кода
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
 
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 
        private double  _x;
        private double  _y;
 
        public double X { get=>_x; set {_x=value; OnPropertyChanged("X");} }
        public double Y { get=>_y; set{_y=value; OnPropertyChanged("Y");}}
 
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
 
            X = 111;
            Y = 111;
        }
    }
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727718
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Roman Mejtes
Код: xml
1.
2.
3.
4.
5.
<Canvas Name="Canvas">
    <Rectangle Fill="Black" Width="60" Height="60" 
               Canvas.Left="{Binding X, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}" 
               Canvas.Top="{Binding Y, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MainWindow}}}"/>
</Canvas>


вот рабочий вариант вашего примера Roman Mejtes проясните, пожалуйста. А то я чего-то недопонял.
Биндинги Вы исправили. Но в самом окне эти свойства реализованы без INotifyPropertyChanged. Установка значений идёт уже после инициализации элементов окна.
А каким образом тогда элемент узнаЁт об изменении значения свойства?
Или интерфейс INotifyPropertyChanged не всегда нужен?
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727720
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А он и не узнаёт.
Роман исправил только привязку. А если хочешь, чтобы изменение свойства отслеживалось - делай нотификацию. Но тут может проще даже сделать DependencyProperty - нет смысла добавлять к DependencyObject (коим является Window) еще и INotifyPropertyChanged
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727721
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Eld HaspУстановка значений идёт уже после инициализации элементов окна.Не скажу со 100% уверенностью, но вроде бы привязки будут обработаны уже после отработки конструктора, поэтому начальная значения привязка все равно увидит.

В любом случае, считывание свойств привязкой идет в потоке пользовательского интерфейса, даже если я меняю их (и издаю нотификацию) в другом потоке. Так что, думаю, что вышесказанное сработает (проверять лень ))
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727724
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.ProEld HaspУстановка значений идёт уже после инициализации элементов окна.Не скажу со 100% уверенностью, но вроде бы привязки будут обработаны уже после отработки конструктора, поэтому начальная значения привязка все равно увидит.

В любом случае, считывание свойств привязкой идет в потоке пользовательского интерфейса, даже если я меняю их (и издаю нотификацию) в другом потоке. Так что, думаю, что вышесказанное сработает (проверять лень ))
Результаты экспериментов.
Если устанавливать привязку через ElementName, то инициализацию свойства надо проводить, до InitializeComponent();. Если позже - без INPC - значения не изменяются.
Если устанавливать через DataContext (как в моём примере), то значения можно установить в любом месте конструктора окна. Если позже (допустим в Loaded) - то тоже без INPC изменения не замечаются.
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727936
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Eld HaspВы задали вопрос http://www.cyberforum.ru/wpf-silverlight/thread2345072.html#post13027693
И я Вам там ответил. В том числе дал полностью рабочий пример кода. Интерфейс INotifyPropertyChanged для свойств предназначенных для привязывания обязателен.
Вот тот пример кода
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
 
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 
        private double  _x;
        private double  _y;
 
        public double X { get=>_x; set {_x=value; OnPropertyChanged("X");} }
        public double Y { get=>_y; set{_y=value; OnPropertyChanged("Y");}}
 
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
 
            X = 111;
            Y = 111;
        }
    }



Да, теперь я вижу, что ваш вариант тоже работает и даже лучше. Простите мне мою невнимательность. Дело в том, что я сейчас пытаюсь написать небольшую игру и заодно изучить WPF(и патерн MVVM). Чтобы не кидать сюда весь мой неоптимизированный код на 500 строк я выделил лишь часть, но теперь понимаю, что выделил не то. При помощи ListBox мне было необходимо поместить в Canvas определённое количество элементов(допустим прямоугольников), которые должны быть расположены по всей плоскости Canvas так, будто они находятся в WrapPanel:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<ListBox Name="OutListBox" Background="Black" ItemsSource="{Binding OutputGameFields}" SelectedItem="{Binding OutputGameFieldSelected}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Rectangle Width="60" Height="60" Fill="White" Canvas.Left="{Binding X, Mode=OneWay}" Canvas.Top="{Binding Y, Mode=OneWay}"/>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                        <ListBox.ItemsPanel>
                            <ItemsPanelTemplate>
                                <Canvas Background="Black" Width="600" Height="600"/>
                            </ItemsPanelTemplate>
                        </ListBox.ItemsPanel>
</ListBox>



Код: 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.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
public class MainViewModel : INotifyPropertyChanged
    {    
        private GameField outputGameFieldSelected;

        //Список, передаваемый в ListBox, таким образом на каждый объект класса GameField приходится один прямоугольник
        public ObservableCollection<GameField> OutputGameFields { get; set; } = new ObservableCollection<GameField>();
        public MainViewModel()
        {
          CreateGameField();
        }


        //Просто селектор, реализацию которого я вырезал
        public GameField OutputGameFieldSelected
        {
            get => outputGameFieldSelected;
            set
            {
                if (Equals(value, outputGameFieldSelected)) return;
                ItemBuilder(value);
            }
        }

        public void CreateGameField()
        {
            OutputGameFields.Clear();
            //Создание элементов и установка координат для каждого
            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    OutputGameFields.Add(new GameField(){ X = j * 60, Y = i * 60 });
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
}

public class GameField : INotifyPropertyChanged
    {
        private double x;
        private double y;

        //Поля, которые неправильно привязаны
        public double X
        {
            get => x;
            set
            {
                x = value;
                OnPropertyChanged();
            }
        }
        public double Y
        {
            get => y;
            set
            {
                y = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }



К сожалению в данном случае проблема не в реализации интерфейса INotifyPropertyChanged, а в плохих биндингах. Не могли бы Вы помочь ещё раз, пожааалуйста?
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727938
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
111DarkFox111При помощи ListBox мне было необходимо поместить в Canvas определённое количество элементов(допустим прямоугольников), которые должны быть расположены по всей плоскости Canvas так, будто они находятся в WrapPanel:А зачем? Скажите листбоксу, чтобы использовал WrapPanel в качестве внутренней панели - и все.
А если функционала WrapPanel недостаточно, сделайте свою панель. Это проще, чем кажется, и сделает вас волшебником в своих глазах )
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727940
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
  <ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled">
    <ListBox.ItemsPanel>
      <ItemsPanelTemplate>
        <WrapPanel />
      </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
    <TextBlock Text="wwwwwwwww" />
  </ListBox>
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727943
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
111DarkFox111.......... При помощи ListBox мне было необходимо поместить в Canvas определённое количество элементов(допустим прямоугольников), которые должны быть расположены по всей плоскости Canvas так, будто они находятся в WrapPanel ..........Честно говоря совершено не понял Вашей идеи. Если нужна WrapPanel почему тогда её и не использовать как написал Shocker.Pro ? Зачем из Canvas имитировать WrapPanel ?
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727944
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да я знаю про WrapPanel и использовал его до этого, но теперь мне нужны координаты, потому что я собираюсь перемещать элементы уже после добавления их в Canvas.
Создание своей собственной панели? Я не знал о такой возможности, но мне кажется что здесь она не поможет. Даже если я объединю функционал WrapPanel и Canvas мне всё равно будут нужны привязки координат элементов.
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727946
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
111DarkFox111Да я знаю про WrapPanel и использовал его до этого, но теперь мне нужны координаты, потому что я собираюсь перемещать элементы уже после добавления их в Canvas.
Создание своей собственной панели? Я не знал о такой возможности, но мне кажется что здесь она не поможет. Даже если я объединю функционал WrapPanel и Canvas мне всё равно будут нужны привязки координат элементов.То есть, есть какой-то набор фигур. В списке есть уже правильно расставленные координаты. Надо только по этим координатам вывести эти фигуры.
Хотя в начале расстановка подобна WrapPanel, потом она меняется.
Я правильно понял?
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727951
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
создайте свою панель и размещайте там элементы как вашей душе угодно
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727952
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сейчас объясню максимально подробно. Эти фигуры(прямоугольники), на самом деле являются игровым полем, по которому будет перемещаться игровой персонаж. У каждого такого прямоугольника есть свойства, определяющие является ли он обычной поверхностью или стеной. Собственно для обработки коллизии персонажа со стеной мне необходимы координаты. Да и для перемещения самого персонажа нужны его координаты. Правда как я буду добавлять персонажа на Canvas после всех фигур в патерне MVVM я ещё не придумал.
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727953
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Например, панель может читать присоединяемые свойства своих детей как, к примеру, поступает Grid. В то же время эти свойства можно привязывать к модели представления.

То есть объявить координаты присоединяемыми свойствами и нацепить их на свои элементы
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727960
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
111DarkFox111Сейчас объясню максимально подробно. Эти фигуры(прямоугольники), на самом деле являются игровым полем, по которому будет перемещаться игровой персонаж. У каждого такого прямоугольника есть свойства, определяющие является ли он обычной поверхностью или стеной. Собственно для обработки коллизии персонажа со стеной мне необходимы координаты. Да и для перемещения самого персонажа нужны его координаты. Правда как я буду добавлять персонажа на Canvas после всех фигур в патерне MVVM я ещё не придумал.Здесь я точно Вам не помощник. Я сам то ещё 4 месяцев нет как с WPF познакомился.
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727962
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.ProНапример, панель может читать присоединяемые свойства своих детей как, к примеру, поступает Grid. В то же время эти свойства можно привязывать к модели представления.

То есть объявить координаты присоединяемыми свойствами и нацепить их на свои элементы

Похоже, что самый простой способ для меня сейчас это всё же сделать через Grid и создать метод, который будет конвертировать значения X и Y в значения для Margin. В любом случае спасибо, что потратили время на вопросы такого неофита как я.

Можете ткнуть носом в материал о том как создавать свои панели?
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727964
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727967
111DarkFox111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727968
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм, для такого поля вообще подойдет обычный грид с набором фиксированных строк и столбцов, а координаты хранить в Grid.Column и Grid.Row
...
Рейтинг: 0 / 0
Привязка координат элемента в Canvas
    #39727971
Eld Hasp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.ProХм, для такого поля вообще подойдет обычный грид с набором фиксированных строк и столбцов, а координаты хранить в Grid.Column и Grid.RowДа, действительно так. Зачем выдумки с ListBox и Canvas?
Один Grid для фона, и сверху его накрыть другой панелью, можно Canvas, для персонажа.
...
Рейтинг: 0 / 0
25 сообщений из 29, страница 1 из 2
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Привязка координат элемента в Canvas
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]