powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Binding и UserControl
42 сообщений из 42, показаны все 2 страниц
Binding и UserControl
    #37696505
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уже второй день курим все что можно...
Проблема в том что никак не могу заставить работать Binding своем контроле.
Проект большой так что написал усеченный аналог с той же проблемой.

Если привязать Dependency Property TheWidthHeightProperty контрола RedRectangel прямо к свойству TestWidthHeight (тип WidthHeight) в окна Window1 объекту, то квадрат размер менять не хочет хотя TestWidthHeight.Width и TestWidthHeight.Нight меняются (это видно по Labels)

А если привязать свойства Width и Height контрола RedRectangel к соответствующим свойствам объекта типа WidthHeight то все в шоколаде. Но этот вариант не катит. В реальном объекте в контроле, роль которого играет RedRectangel, очень много преобразований данных для того что бы отобразить графический объект согласно данных из базы. Придется писать кучу свойств зависимости и конвертеров, а алгоритм уже работает. После нажатия на кнопку программа не приходит в OnTheWidthHeightPropertyChanged, а по задумке вроде как должна...

Полный source "прикручен" к сообщению. Убрал все заголовки и объявления так как не используется ничего кроме стандартных библиотек.
Итак вот код.

Window1.xaml
Код: xml
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.
<Window ... 
    Name="TheControl">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <local:RedRectangel TheWidthHeight="{Binding ElementName=TheControl, Path=TestWidthHeight, Mode=TwoWay}" x:Name="rect" HorizontalAlignment="Center" VerticalAlignment="Center"></local:RedRectangel>

        <StackPanel Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Center">
            <TextBlock Margin="10">Width (Bindin):</TextBlock>
            <TextBlock Margin="10" Text="{Binding ElementName=TheControl, Path=TestWidthHeight.Width}"></TextBlock>
            <TextBlock Margin="10">Height (Bindin):</TextBlock>
            <TextBlock Margin="10" Text="{Binding ElementName=TheControl, Path=TestWidthHeight.Height}"></TextBlock>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Grid.Row="2">
            <Button VerticalAlignment="Center" Width="70" Height="30" Margin="10" Click="Button_Click">+(Binding)</Button>
            <Button VerticalAlignment="Center" Width="70" Height="30" Margin="10" Click="Button_Click_1">-(Binding)</Button>
        </StackPanel>

    </Grid>
</Window>



Window1.xaml.cs
Код: 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.
namespace TestBinding
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        WidthHeight testWidthHeight = new WidthHeight();
        public WidthHeight TestWidthHeight
        {
            get { return testWidthHeight; }
            set { testWidthHeight = value; }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TestWidthHeight.Height++;
            TestWidthHeight.Width++;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            TestWidthHeight.Height--;
            TestWidthHeight.Width--;
        }
    }
}



Код: xml
1.
2.
3.
4.
5.
6.
RedRectangel.xaml
<UserControl>
    <Grid>
        <Rectangle Fill="Red" x:Name="rect"></Rectangle>
    </Grid>
</UserControl>




RedRectangel.xaml.cs
Код: 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.
namespace TestBinding
{
    public partial class RedRectangel : UserControl
    {
        public RedRectangel()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty TheWidthHeightProperty =
                DependencyProperty.Register("TheWidthHeight", typeof(WidthHeight), typeof(RedRectangel), new UIPropertyMetadata(null, OnTheWidthHeightPropertyChanged));

        public WidthHeight TheWidthHeight
        {
            get { return (WidthHeight)GetValue(TheWidthHeightProperty); }
            set { SetValue(TheWidthHeightProperty, value); }
        }

        private static void OnTheWidthHeightPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            RedRectangel thisControl = dependencyObject as RedRectangel;
            thisControl.rect.Width = ((WidthHeight)e.NewValue).Height;
            thisControl.rect.Height = ((WidthHeight)e.NewValue).Width;
        }

    }
}



WidthHeight.cs
Код: 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.
namespace TestBinding
{
    public class WidthHeight : INotifyPropertyChanged
    {
        private int width = 50;
        /// <summary>
        /// Gets or sets the pathology results.
        /// </summary>
        /// <value>
        /// The pathology results.
        /// </value>
        public int Width
        {
            get { return width; }
            set
            {
                width = value;
                OnPropertyChanged("Width");
            }
        }

        private int height = 50;
        /// <summary>
        /// Gets or sets the pathology results.
        /// </summary>
        /// <value>
        /// The pathology results.
        /// </value>
        public int Height
        {
            get { return height; }
            set
            {
                height = value;
                OnPropertyChanged("Height");
            }
        }

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <param name="name">The name.</param>
        private void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)//BiopsyCore
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

    }
}
...
Рейтинг: 0 / 0
Binding и UserControl
    #37696692
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.AffectsMeasure ,
new PropertyChangedCallback(OnPropertyChanged)));
...
Рейтинг: 0 / 0
Binding и UserControl
    #37696693
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вместо new UIPropertyMetadata
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698491
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa,

у него кстати есть метод через new UIPropertyMetadata(null, OnTheWidthHeightPropertyChanged).


alex_myzn ,
тебе надо идти самым простым путем.

в студии debugging->output window -> databinding=all и dependency property=all включаешь.


в своем биндинге делаешь так:

Код: xml
1.
2.
<local:RedRectangel  xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
 TheWidthHeight="{Binding ElementName=TheControl, Path=TestWidthHeight, Mode=TwoWay,diagnostics:PresentationTraceSources.TraceLevel=High}" x:Name="rect" HorizontalAlignment="Center" VerticalAlignment="Center"></local:RedRectangel>


и теперь смотришь output и ли immediate window и думаю, ты сразу поймешь, что к чему.
обычно, когда ты юзаешь binding к user control, то он делается, раньше чем все инициализируется и ты ничего не получаешь. но у тебя может быть по другому.

логи приложи в следующий раз.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698517
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо SeVa за ответ, тут действительно еще одна, из многих тысяч, "полочка" WPF, но к сожалению это не помогло.
Я тут немного изменил программку для большей очевидности и прикрепил его к сообщению...
Мне кажется что проблема лежит где-то между классом WidthHeight и свойством зависимости TheWidthHeightProperty в RedRectangel.
Дело в том что изменение Width или Height в классе WidthHeight вовсе не приводит к вызову OnTheWidthHeightPropertyChanged для TheWidthHeightProperty. С одной стороны в принципе это понятно.
INotifyPropertyChanged из WidthHeight отработал честно оповестив всех к привязанных в его свойствам через свойства зависимостей, что произошло изменение, это видно из работы зеленого квадрата. А вот то что касается бордового то ни кто и не говорил что изменения свойств в классе приводит к изменению свойства зависимости этого типа, т.е. ни кто не гарантирует вызов метода OnTheWidthHeightPropertyChanged в RedRectangel.
А вот с другой стороны хотелось бы понять как это сделать как заставить вызываться этот метод когда произошли подобные изменения?
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698580
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо AlexeiK,
Это действительно очень классный класс (прошу прощения за тавтологию). Показал он следующее:

System.Windows.Data Warning: 52 : Created BindingExpression (hash=14347911) for Binding (hash=52727599)
System.Windows.Data Warning: 54 : Path: 'TestWidthHeight'
System.Windows.Data Warning: 57 : BindingExpression (hash=14347911): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 58 : BindingExpression (hash=14347911): Attach to TestBinding.RedRectangel.TheWidthHeight (hash=51393439)
System.Windows.Data Warning: 63 : BindingExpression (hash=14347911): Resolving source
System.Windows.Data Warning: 66 : BindingExpression (hash=14347911): Found data context element: <null> (OK)
System.Windows.Data Warning: 70 : Lookup name TheControl: queried StackPanel (hash=26756241)
System.Windows.Data Warning: 74 : BindingExpression (hash=14347911): Activate with root item Window1 (hash=23264094)
System.Windows.Data Warning: 104 : BindingExpression (hash=14347911): At level 0 - for Window1.TestWidthHeight found accessor RuntimePropertyInfo(TestWidthHeight)
System.Windows.Data Warning: 100 : BindingExpression (hash=14347911): Replace item at level 0 with Window1 (hash=23264094), using accessor RuntimePropertyInfo(TestWidthHeight)
System.Windows.Data Warning: 97 : BindingExpression (hash=14347911): GetValue at level 0 from Window1 (hash=23264094) using RuntimePropertyInfo(TestWidthHeight): WidthHeight (hash=14303791)
System.Windows.Data Warning: 76 : BindingExpression (hash=14347911): TransferValue - got raw value WidthHeight (hash=14303791)
System.Windows.Data Warning: 85 : BindingExpression (hash=14347911): TransferValue - using final value WidthHeight (hash=14303791)

Вроде все в норме. До этого тоже не было ошибок с binding.

Кстати я знаю что надо создавать WidthHeight до InitializeComponent(). Именно в этот момент и вызывается OnTheWidthHeightPropertyChanged тот единственный раз, так как произошло изменение самого объекта. Именно в этот момент квадраты становятся 50х50. А дальше ничего... :-(

Я не нашел где устанавливаются опции о которых ты говорил
AlexeiKSeVa,
в студии debugging->output window -> databinding=all и dependency property=all включаешь.

в tools -> options -> debugging ничего подобного нет. У меня VS2008 SP1.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698635
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myznСпасибо SeVa за ответ, тут действительно еще одна, из многих тысяч, "полочка" WPF, но к сожалению это не помогло.
Я тут немного изменил программку для большей очевидности и прикрепил его к сообщению...
Мне кажется что проблема лежит где-то между классом WidthHeight и свойством зависимости TheWidthHeightProperty в RedRectangel.
Дело в том что изменение Width или Height в классе WidthHeight вовсе не приводит к вызову OnTheWidthHeightPropertyChanged для TheWidthHeightProperty. С одной стороны в принципе это понятно.
INotifyPropertyChanged из WidthHeight отработал честно оповестив всех к привязанных в его свойствам через свойства зависимостей, что произошло изменение, это видно из работы зеленого квадрата. А вот то что касается бордового то ни кто и не говорил что изменения свойств в классе приводит к изменению свойства зависимости этого типа, т.е. ни кто не гарантирует вызов метода OnTheWidthHeightPropertyChanged в RedRectangel.
А вот с другой стороны хотелось бы понять как это сделать как заставить вызываться этот метод когда произошли подобные изменения?
Вполне ожидаемое поведение. При сеттерах WidthHeight выдается сообщение об изменении конкретного свойства, а не всего объекта, к которому делается связывание в красном прямоугольнике.
Не совсем понятно для чего нужен подобный сценарий, решений может быть несколько:
- в OnTheWidthHeightPropertyChanged задавать нужные binding'и, а не делать изменения значений
- создать behavior, в OnAttached задавать нужные связывания
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698696
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa- в OnTheWidthHeightPropertyChanged задавать нужные binding'и, а не делать изменения значений
Этот вариант не подходит та как именно OnTheWidthHeightPropertyChanged и не вызывается и что бы внутри него не написать все равно работать не будет.

SeVa- создать behavior, в OnAttached задавать нужные связывания
Это весьма интересно, но из того что я успел найти в MSDN пока ничего не понятно. Может есть ссылка на пример?

Я тут попробовал обойти это...
В классе WidthHeight создал свойство MirrorWidthHeight которое указывает на сам объект:
Код: 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.
        public WidthHeight MirrorWidthHeight
        {
            get
            {
                return this;
            }
            set
            {
                OnPropertyChanged("MirrorWidthHeight");
            }
        }

        public int Width
        {
            get { return width; }
            set
            {
                width = value;
                MirrorWidthHeight = this;
                OnPropertyChanged("Width");
            }
        }

        public int Height
        {
            get { return height; }
            set
            {
                height = value;
                MirrorWidthHeight = this;
                OnPropertyChanged("Height");
            }
        }



и привязался к нему...

Код: xml
1.
<local:RedRectangel  TheWidthHeight="{Binding ElementName=TheControl, Path=TestWidthHeight.MirrorWidthHeight, Mode=TwoWay}" x:Name="rect" Margin="5" Fill="DarkRed"></local:RedRectangel>



Но это тоже не возымело действия. Хотя почему, уже совсем не очевидно. OnTheWidthHeightPropertyChanged не вызывается ни в какую, хотя привязка уже осуществляется на свойство WidthHeight...
Далее планирую следующий подход. Пробую написать еще один вариант с wraper для WidthHeight и вызовом PropertyChanged через событие изменения содержимого wraper...

Да... Вот новый вариант программки.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698698
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Упс... забыл файлик
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698711
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть Expression Blend SDK. Примеры для него
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698721
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVaНе совсем понятно для чего нужен подобный сценарий
Я описал почему мы пошли по этому пути.
alex_myznВ реальном объекте в контроле, роль которого играет RedRectangel, очень много преобразований данных (в том числе и 3D) для того что бы отобразить графический объект согласно данных из базы. Придется писать кучу свойств зависимости и конвертеров, а алгоритм уже работает.
хотя конечно это правильный подход...

PS
Да тут нашел очень простой способ который решил бы все проблемы... (это из реального проекта)
Код: c#
1.
2.
3.
            var dataContext = this.DataContext;
            DataContext = null;
            DataContext = dataContext;


Но честное слово это все ламерством попахивает...
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698738
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVaЕсть Expression Blend SDK. Примеры для него

Огромное спасибо вам за то что е жалеете время что бы мне помочь.
Я так и понял когда начал читать про behaviors. Это все для Framework 4, да и Expression 4-й нужен, с практической точки зрения это на данном этапе невозможно реализовать.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698814
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пока вопрос остается открытым...
...
Рейтинг: 0 / 0
Binding и UserControl
    #37698883
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blend SDK for Net 3.5 .

Одного вызова OnTheWidthHeightPropertyChanged вполне достаточно, чтобы сделать нужные binding'и (SetBinding), тогда все изменения будут отслеживаться на автомате. Но, судя по примеру из реального проекта с DataContext, нужно еще отслеживание изменения всего объекта, это можно сделать отслеживая событие DataContextChanged.
Но если приходится извращаться, то это говорит о том, что решение не в духе wpf.
Суть всей затеи непонятна, совершенно непрозрачен показанный вариант с RedRectangel. Этот функционал можно просто реализовать с помощью неявных или явных шаблонов для WidthHeight без всяких мультиков.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699032
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Следуйте принципам MVVM и все будет проще
Код: 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.
public MyModel : INotifyPropertyChanged
{
    public int Width //....;
    public int Height //....; 
}

public MyViewModel : : INotifyPropertyChanged
{
   pubic MyModel Model //....
}

public MyControl
{

   public MyControl()
  {
     //....
    this.DataContextChanged += OnDataContextChanged();
  }

  private void OnDataContextChanged(///...)
  {
    //CleanBinding
    //SetBinding
}
   
}



PS Для сложной логики самое место - ViewModel
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699085
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVaОдного вызова OnTheWidthHeightPropertyChanged вполне достаточно, чтобы сделать нужные binding'и (SetBinding), тогда все изменения будут отслеживаться на автомате.
А почему же они не отслеживаются когда binding сделан непосредственно в XAML? Уж куда проще то...

На счет DataContext, это я так привел, для примера, решение со сбросом DataContext, заполнением из базы и последующим заполнением из базы считаю неправильным, та как согласно технологии WPF Binding именно и предназначен для того сто бы разные объекты смотря на одни и те же данные имели одинаковые значения и обновлялись не зависимо от того кто из них или вообще некое внешнее воздействие привело к обновлению данных.
Кстати сам Control не влияет на дату, редактирование происходит в другом месте. Данные записываются в некую иерархическую коллекцию (она то и есть DataContext), один из пунктов которой и есть информация для Control. Так вот после этих изменений и возникает необходимость обновить сам Control.

SeVaСуть всей затеи непонятна, совершенно непрозрачен показанный вариант с RedRectangel. Этот функционал можно просто реализовать с помощью неявных или явных шаблонов для WidthHeight без всяких мультиков.
Это просто пример иллюстрирующий проблему. RedRectangel это просто некий UserControl, на самом деле он довольно сложный и свойств у него несколько десятков. Кнопки (мультики) призваны что бы воздействовать на данные. И причем здесь шаблоны я вообще не понимаю. Та что я не совсем понял что вы имеете ввиду.

SeVaСледуйте принципам MVVM и все будет проще
Вот им то я и стараюсь следовать. Все решается через Binding и DependencyProperty. Данные в отдельном классе (WidthHeight) визуальное представление в отдельном (RedRectangel) . Бизнес логика в отдельном.(Window1). Все связи через Binding и DependencyProperty. Может конечно я что-то не так понимаю в MVVM.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699097
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати попытка написать Wrapper тоже потерпела фиаско. Ну не хочет он дергать этот чертов OnTheWidthHeightPropertyChanged!!!!
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699160
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

запустил твой пример.
работает.
Код: xml
1.
<local:RedRectangel xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" TheWidthHeight="{Binding ElementName=TheControl, Path=TestWidthHeight.WrapWidthHeight, Mode=TwoWay,diag:PresentationTraceSources.TraceLevel=High}" x:Name="rect" Margin="5" Fill="DarkRed"></local:RedRectangel>



вот этот биндинг работает.
я меняю в коде c 50,50 на 100,100 и при запуске вижу 100, 100 или 50,50.
ты этого хотел достичь?
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699266
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexeiK,
Очень странно... Именно этот binding у меня и не работает. Алексей скажите а какой из 2-х квадратов работает, красный или зеленый? У меня работает зеленый.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699326
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

слушай, я тут просто разобрался.
ты хочешь чтобы изменяя локальную переменную в window , изменялись параметры ширина и длина прямоугольников.
ну хорошо это правильное желание.
токо ты забыл, про то, что window должна реализовать inotifypropertychanged , чтобы дать понять все, что TestWidthHeight изменилась.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
private void Button_Click(object sender, RoutedEventArgs e)
        {

            //rect.SetValue(RedRectangel.TheWidthHeightProperty, TestWidthHeight);
            TestWidthHeight = new WidthHeight(TestWidthHeight.Height, TestWidthHeight.Width);
            TestWidthHeight.Height += 5;
            TestWidthHeight.Width += 5;
            OnPropertyChanged("TestWidthHeight");
        }


далее делаем так.
и все работает.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699332
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
приложу файл
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699336
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

то есть, оповестить о том, что свойство изменилось удается через NEW.
а через inotifypropertychanged не удается.
не знаю, мож у тебя косяк в коде где. слолжно на c# читать.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699528
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

Gосмотрел я твой код. Запускал проект TestBinding.
В ркасном квадрате ты изменяешь свойства Width и Height.
Это встроенные свойства зависимостей объекта Rectangle. А как ты должен знать - привязка без проблем работает со свойствами зависимостей. Поэтому реализовав интерфейс INot - свойства Width и Height (как свойства зависимостей) видят эти изменение, которые ты делаешь через кнопки.

Теперь что касается красного квадрата.
Ты пытаешься привязать к свойству TheWidthHeight - TestWidthHeight.MirrorWidthHeight. При этом TestWidthHeight.MirrorWidthHeight реализует интерфейс INot - поэтому он передает эти изменения свойству TheWidthHeight.
НО... свойство TheWidthHeight не является свойством зависимостей (ты его таким не объявил). Поэтому не удивительно, что красный квадрат у тебя не изменяется.
Объяви TheWidthHeight как свойство зависимостей и у тебя все взлетит
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699534
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

Чуть подправил предыдущее свое сообщение:

Посмотрел я твой код. Запускал проект TestBinding.
В зеленом квадрате ты изменяешь свойства Width и Height.
Это встроенные свойства зависимостей объекта Rectangle. А как ты должен знать - привязка без проблем работает со свойствами зависимостей. Поэтому реализовав интерфейс INot - свойства Width и Height (как свойства зависимостей) видят эти изменение, которые ты делаешь через кнопки.

Теперь что касается красного квадрата.
Ты пытаешься привязать к свойству TheWidthHeight - TestWidthHeight.MirrorWidthHeight. При этом TestWidthHeight.MirrorWidthHeight реализует интерфейс INot - поэтому он передает эти изменения свойству TheWidthHeight.
НО... свойство TheWidthHeight не является свойством зависимостей (ты его таким не объявил), соответственно это свойство не может видеть подаваемые ему изменения. Поэтому не удивительно, что красный квадрат у тебя не изменяется.
Объяви TheWidthHeight как свойство зависимостей и у тебя все взлетит
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699584
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unknownfromrus,

унего же объявлено оно.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
public partial class RedRectangel : UserControl
    {
        public RedRectangel()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty TheWidthHeightProperty =
                DependencyProperty.Register("TheWidthHeight", typeof(WidthHeight), typeof(RedRectangel), new UIPropertyMetadata(null, OnTheWidthHeightPropertyChanged));


ты чтото, не внимательно смотрел.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699613
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexeiK,

Я может не совсем коректно выразился)))
У него в коде в качестве свойства зависимости объявляется TheWidthHeight.

public static readonly DependencyProperty TheWidthHeightProperty =
DependencyProperty.Register("TheWidthHeight", typeof(WidthHeight), typeof(RedRectangel), new UIPropertyMetadata(null, OnTheWidthHeightPropertyChanged));

В методе Register второй параметр typeof(WidthHeight). Знчит в классе WidthHeight должно быть объявлено свойство TheWidthHeight.

Теперь смотрим содержимое класса WidthHeight. Я в нем не увидел объявленное свойство TheWidthHeight. Из всех свойств класса WidthHeight которые у него объявлены я вижу только:

MirrorWidthHeight
Width
Height

Далее в коде у него TheWidthHeight="{Binding ElementName=TheControl, Path=TestWidthHeight.MirrorWidthHeight, Mode=TwoWay}". Поэтому не удивительно что не работает
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699642
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unknownfromrus,

Просьба не набрасываться на меня. У меня есть оправдание - голова не совсем уже работает))). Я понимаю что в предыдущем посте чушь написал))
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699674
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexeiK,

В общем исправляю свой косяк.

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

new UIPropertyMetadata - Предоставляет метаданные свойств для несистемных свойств, которые влияют на отрисовку или пользовательский интерфейс на уровне ядра.
Я не могу утверждать (так как явно этого не нашел). Но есть подозрение, что вызываемый метод при изменении свойства зависимости не будет влиять на на компоновку элементов в панели.

Далее смотрим на популярный метод при регистрации свойств зависимостей:

public class FrameworkPropertyMetadata : UIPropertyMetadata

То FrameworkPropertyMetadata наследуется от нашего уже небезызвестного UIPropertyMetadata.
НО.. при использовании FrameworkPropertyMetadata у него есть такая штука, как FrameworkPropertyMetadataOptions, которая имеет специальные флаги, которые майкрософт просит нас использовать, если мы изменяем свойства зависимостей, которые изменяют размеры эелементов. Даже если порыть в инете, можно увидеть, что если используются пользовательские свойства для изменения компоновки эелементов в панели, то как правило используются фалги типа AffectMesuare (как то так называется). То есть все должно выглядеть как то типа этого:

public static readonly DependencyProperty TheWidthHeightProperty =
DependencyProperty.Register("TheWidthHeight", typeof(WidthHeight), typeof(RedRectangel), new FrameworkPropertyMetadata(50, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnTheWidthHeightPropertyChanged)));

Как можно увидеть, значение по умолчанию у меня равно 50. Но система не понимает, как же так, свойство относится к классу WidthHeight, а я пытаюсь его нашпинговать значением 50 (который имеет либо тип double либо int).
Поэтому осталось побороться со значением по умолчанию.

Если что-то не так то поправьте меня))
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699796
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,
О ЕЕЕЕЕ
Я добил эту дрянь))) Заснул поздно но добил)).
Смотри.
У тебя почти все гуд. Косяк только в одном сейчас объясню подробно.

Код: 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.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
public class WidthHeight : INotifyPropertyChanged
    {
        public WidthHeight()
        {
            Width = 50;
            Height = 50;
            MirrorWidthHeight = this;
        }

        public WidthHeight(int width1, int height1)
        {
            this.Width = width1;
            this.Height = height1;
            MirrorWidthHeight = this;
        }

        /// <summary>
        /// Gets or sets the height of the width.
        /// </summary>
        /// <value>
        /// The height of the width.
        /// </value>
        public WidthHeight MirrorWidthHeight
        {
            get
            {
                return new WidthHeight(this.Height, this.Width);
            }
            set
            {
                OnPropertyChanged("MirrorWidthHeight");
            }
        }

        private int width;
        /// <summary>
        /// Gets or sets the pathology results.
        /// </summary>
        /// <value>
        /// The pathology results.
        /// </value>
        public int Width
        {
            get { return width; }
            set
            {
                width = value;
                MirrorWidthHeight = this;
                OnPropertyChanged("Width");
            }
        }

        private int height;
        /// <summary>
        /// Gets or sets the pathology results.
        /// </summary>
        /// <value>
        /// The pathology results.
        /// </value>
        public int Height
        {
            get { return height; }
            set
            {
                height = value;
                MirrorWidthHeight = this;
                OnPropertyChanged("Height");
            }
        }

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <param name="name">The name.</param>
        private void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)//BiopsyCore
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        

        public override string ToString()
        {
            return Height + " " + Width;
        }
    }



Обрати внимание я убрал лишнее и самое ГЛАВНОЕ сделал изменение в свойстве MirrorWidthHeight.
Проверить что Ширина и высота класса WidthHeight реально изменяется - не проблема - достаточно вывести в тектблок в окошко. В общем с этим все ясно.
В итоге убеждаемся - что с этим все гуд (ну это и так понятно, так как зеленый квадрат изменяется).
Если поставить точку останова в

Код: c#
1.
2.
3.
4.
5.
6.
private static void OnTheWidthHeightPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            RedRectangel thisControl = dependencyObject as RedRectangel;
            thisControl.rect.Width = ((WidthHeight)e.NewValue).Width;
            thisControl.rect.Height = ((WidthHeight)e.NewValue).Height;
        }



то заметишь в старом коде - ничего не происходит. То есть система видит, что КЛАСС WidthHeight не изменяется. Но его внутренние свойства изменяются. Нам осталось система как-то объяснить, что именно класс изменяется, нам как бы на свойство в данный момент этого класса положить)).
Когда ты возвращал в методе MirrorWidthHeight this - ты возвращал текущий класс - то есть он как бы не изменялся. Поэтому система думала что класс не изменился. А вот когда я стал возвращать return new WidthHeight(this.Height, this.Width); в свойстве MirrorWidthHeight, то я каждый раз возвращаю НОВУЮ ссылку класса - то есть по сути система видит изменение класса (а точнее то, что у моего класса новая ссылка). Вот и все волшебство))
...
Рейтинг: 0 / 0
Binding и UserControl
    #37699861
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unknownfromrus,

AlexeiK
alex_myzn,

то есть, оповестить о том, что свойство изменилось удается через NEW.
а через inotifypropertychanged не удается.
не знаю, мож у тебя косяк в коде где. слолжно на c# читать

ну вот, двое уже сошлись в том, как это работает.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700038
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexeiK,

Если бы утром решал этот вопрос - то наверно быстрее бы выяснил. Под вечер реально голова хуже соображает.
Просто че-то не мог уснуть пока не решил эту проблему - смотришь вроде бы все как гуд. Но подсознательно понимаешь, что PropertyChanged в метаданных не запускается - то есть система не видит изменение класса.

А потом так пораскинул мозгами. Ведь действительно, когда мы изменяем типы значений - то для изменения состояния достаточно изменить это самое значение.
А ведь для классов изменение внутренних свойств ничего не говорит. Внутри класса может происходить что угодно - но ссылка все это время будет указывать на одну и ту же память - а значт система понимает, что класс не изменился. Поэтому нужен NEW.
Надо было твое предыдущее сообщение повнимательнее прочитать - съэкономил бы кучу времени))
Я тебе кстати в какой-то ветке вопрос задавал. Что скажешь по поводу Prism? Я посмотрел статьи - понял что убью много времени. А мне в ближайшее время ох как этого не хочется.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700064
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unknownfromrusAlexeiK,
Я тебе кстати в какой-то ветке вопрос задавал. Что скажешь по поводу Prism? Я посмотрел статьи - понял что убью много времени. А мне в ближайшее время ох как этого не хочется.

я не стал отвечать, не хочется флуда :)
я спрашивал про это уже у других, вот почитай : 11374344
там не прям про это, но ты поймешь как найти ответ.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700082
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlexeiK,

Понял, спасибо, пробежался по топику.
Думаю если и займусь этим, то точно не в ближайшее время
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700195
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Огромное спасибо всем за помощь!!!
Как я понял все пришли к выводу что для отработки OnTheWidthHeightPropertyChanged необходимо создать новый объект WidthHeight который используется в свойстве зависимостей. Мы тоже склонялись к этому выводу у себя с группе. К сожалению мы не нашли возможности оповестить систему через INotifyPropertyChanged или что-то другое, что изменение одного из свойств должно оповестить об изменение всего объекта.
Как резюме мне кажется что данный подход является недоработкой в WPF (ну или этот вопрос недостаточно хорошо освещен в первоисточниках). По моему вполне логично предоставление подобного механизма. Представьте довольно сложную иерархическую структуру части которой необходимо визуализировать разными вариантами причем одни из вариантов служат для ее редактирования другие для просмотра в разных представлениях а третье это вообще некие внешние воздействия на структуру извне. Вполне логично что возникает вопрос о том что хотелось бы что бы все изменения синхронно отражались в во всех вариантах ее представления. Что Что же у нас получается, необходимо заново пересоздать часть или всю структуру только если в ней был изменен всего один параметр? Для RedRectangel просто, всего-то длинна и ширина. А если у нас 100 таких RedRectangel и не только их, а еще куча всяких примитивов и не примитивов? Получается что для изменения одного надо пересоздавать все. С моей точки зрения это очень расточительно.

Еще раз огромное спасибо за помощь unknownfromrus, AlexeiK, SeVa. Если у кого-то появилась новая информация по этому вопросу я с удовольствием ее почитаю.

PS В группе мы приняли решения реализовать визуальное представления через создания свойств зависимостей и привязки для каждого параметра отдельно, то есть так как считается "правильным".
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700208
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

Не обязательно для 100 изменений одного и того же свойства создавать 100 экземпляров класса.
Я думаю ты уловил основную суть - для того, чтобы свойство зависимости поняло что произошло изменение (в твоем случае) надо изменять ссылку на класс.
А что тебе мешает создать ВСЕГО 2 объекта класса и потом каждый раз их менять. По сути ты будешь иметь две разные ссылки на память -а значит система будет понимать что произошло изменение. Экономия ресурсов как бы налицо.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700296
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
unknownfromrus,
Это конечно решение вопроса, но согласись это больше смахивает на некие пляски с бубном чем на нормальное, логичное а потому правильное решение. Представать что у тебя целый лист таких объектов, Теперь где-то в сторонке лежит объект который играет роль сменного белья. Ты хочешь поменять белье, берешь этот объект натягиваешь его на себя а старый кладешь на его место теперь кто-то другой тоже хочет поменять свое белье, сбрасывает старое хватает твое, наскоро его стирает, потом запихивает в карманы все что у него было в старом и кладет старое на место "общей подменки"... Так или иначе это все выглядит не очень аппетитно как с точки зрения гигиены так и с точки зрения технологии. :-)
Это конечно шутка все. Мне вообще кажется очень странным что отсутствует механизм поддерживающий оповещение при изменении свойств объекта. При всем количестве, превышающим все разумные пределы, полочек по которым разложена вся технология WPF, не нашлось полочки для подобной простой вещи.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700347
SeVa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[quot alex_myzn]
Как резюме мне кажется что данный подход является недоработкой в WPF (ну или этот вопрос недостаточно хорошо освещен в первоисточниках). По моему вполне логично предоставление подобного механизма. Представьте довольно сложную иерархическую структуру части которой необходимо визуализировать разными вариантами причем одни из вариантов служат для ее редактирования другие для просмотра в разных представлениях а третье это вообще некие внешние воздействия на структуру извне. Вполне логично что возникает вопрос о том что хотелось бы что бы все изменения синхронно отражались в во всех вариантах ее представления. Что Что же у нас получается, необходимо заново пересоздать часть или всю структуру только если в ней был изменен всего один параметр? Для RedRectangel просто, всего-то длинна и ширина. А если у нас 100 таких RedRectangel и не только их, а еще куча всяких примитивов и не примитивов? Получается что для изменения одного надо пересоздавать все. С моей точки зрения это очень расточительно.
[/quot
Все в порядке с wpf и нет там никаких недоработок. У вас просто нет понимания его binding'a и вы выдумываетет свой.
xaml - единственная технология, которая позволяет без всяких мультиков иметь надцать представлений.
Суть проста: DataContext для объекта, binding - для свойств, чтобы не было лишних телодвижений.
В примере вместо того, чтобы привязать свойства прямоугольника напрямую(это можно сделать очень просто), вы начинаете усложнять себе жизнь с никому не нужными спецконтролами и зависимыми свойствами. Ваш спецконтрол- частный вариант, в wpf контекст может быть любой.
Меняйте концепцию
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700384
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SeVa,
Что мы и делаем. :-)
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700733
unknownfromrus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

Посмотрел внутреннюю кухню DependencyPropertyChangedEventArgs. Именно он определяет изменилось значение свойства зависимости или нет.

Действительно печально, что Майкрософт не предусмотрели этот момент. Если он как-о решается (исключая создание нового класса) - то я этого решения не смог найти.

Единственное что - внутри DependencyPropertyChangedEventArgs увидел что есть методы Equals, а также переопределены операторы == и !=. Вот именно они и информируют PropertyChangedCallback о том, произошло изменение или нет.
Надеюсь Майкрософт в будущем добавит что-то, чтобы мы могли в коде указывать DependencyPropertyChangedEventArgs как сравнивать совйства зависимости, если мы подаем класс.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700812
alex_myzn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А знаете что... Я похоже нашел решение нашей проблемы.
"Свойства зависимости и уведомления" Чарльз Петцольд
Просмотрев наскоро эту статью я понял что класс Freezable реализует эту возможность...
Чарльз ПетцольдКласс Freezable представляет грубый силовой подход к получению уведомлений об изменениях в объектах зависимости.

Например, PathGeometry происходит от Freezable. Оно содержит свойство Figures («Рисунки») типа PathFigureCollection, также происходящего от Freezable. PathFigureCollection содержит объекты типа PathFigure, также происходящего от Freezable. PathFigure содержит свойство, именуемое Segments («Сегменты») типа PathSegmentCollection, также Freezable. PathSegment происходит от Freezable и является базовым классом для классов типа PolyLineSegment и PolyBezierSegment. Эти классы содержат свойства, именуемые Point («Точка») типа PointCollection, также происходящего от Freezable.

Общий эффект: при изменении любой отдельной точки уведомления об изменении прокатываются по всей иерархии объектов и вызывают полную перерисовку графического объекта.

По моему это то что надо. Ну что какие идеи?
...
Рейтинг: 0 / 0
Binding и UserControl
    #37700816
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

ну да хорошая штука.
пробуй в своем примере, код выложи.
...
Рейтинг: 0 / 0
Binding и UserControl
    #37702474
AlexeiK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alex_myzn,

ну как?
интересно же.
...
Рейтинг: 0 / 0
42 сообщений из 42, показаны все 2 страниц
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Binding и UserControl
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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