Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > Binding элементов внутри коллекции


Автор: lennyomg 29.10.2010, 10:22
Есть собственный UserControl, в нем есть список "неких параметров", который (список) может заполняться из XAML и есть класс, описывающий "некие параметры". UserControl находится на WPF форме.

Как сбиндить элементы внутри списка параметров в UserControl со свойства окна WPF (т.е. для каждого элемента своё свойсто).

Код ЮзерКонтрола
Код

public class ParameterStorage: UserControl
{
        public ArrayList Parameters
        {
            get { return (ArrayList)GetValue(ParametersProperty); }
            set { SetValue(ParametersProperty, value); }
        }

        public static readonly DependencyProperty ParametersProperty =
            DependencyProperty.Register("Parameters", typeof(ArrayList), typeof(ParameterStorage),
            new UIPropertyMetadata(new ArrayList()));        
    }


Код класса параметров. В ArrayList будут именно экземпляры этого класса.
Код

public class Parameter: DependencyObject
    {
        public int Value
        {
            get { return (int)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(int), typeof(Parameter), new UIPropertyMetadata(-1));
    }


Разметка формы
Код

<Grid>
        <my:ParameterStorage x:Name="myPS">
            <my:ParameterStorage.Parameters>
                <my:Parameter Value="{Binding PValue1}" />
                <my:Parameter Value="{Binding PValue1}" />
            </my:ParameterStorage.Parameters>
        </my:ParameterStorage>
    </Grid>


Ну и код формы
Код

public partial class MainWindow : Window
    {
        public int PValue1
        {
            get { return (int)GetValue(PValue1Property); }
            set { SetValue(PValue1Property, value); }
        }

        public static readonly DependencyProperty PValue1Property =
            DependencyProperty.Register("PValue1", typeof(int), typeof(MainWindow), new UIPropertyMetadata(2));
        
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

        private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            PValue1 = 1;
          // по идее в этом месте, в соответствии с биндингом, оба элемента в myPS.Parameters должны быть равны '1'
          // (ну точнее свойства Value у них должны быть равны 1), но ничего подобного увы не случается, значения остаются такими же как были
        }
    }


Может кто знает чего не хватает. Заранее спасибо

Автор: Kaerus 2.11.2010, 22:38
Проблема здесь
Код

<my:Parameter Value="{Binding PValue1}" />

К сожалению что бы биндинг здесь сработал - класс Parameter должен быть унаследован минимум от FrameworkElement, потому что биндинг без указания источника использует свойство DataContex для поиска источника вверх по визуальному дереву. А это значит что DataContext могут использовать только контролы и их свойства.

Автор: lennyomg 2.11.2010, 23:07
спасибо за ответ

попробовал переписать наследование вот так
Код

public class Parameter : FrameworkElement
{
...

но к сожалению ничего не изменилось

затем вчитался в ответ снова и попробовал следующее: напрямую задал значение датаконтексту параметра (до этого там был null)
получилось что то вроде этого (код на форме)
Код

private void Window_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ((Parameter)myPS.Parameters[0]).DataContext = this; // после этой заветной строчки для 0-го элемента биндинг начал работать как нужно
            PValue1 = 1;
        }


а теперь вопрос... как сделать так, что бы датаконтекст автоматически брался от родителя
хотя-бы в каком направлении копать
заранее спасибо

Автор: Kaerus 3.11.2010, 00:25
1) Не надо забывать что FrameworkElement является базовым классом для контролов, а не для произвольных dependecy классов (к примеру у него есть свойства Width и Height)
2) DataContex работает только для элементов визуального дерева, то что ты добавил элемент типа FrameworkElement в список не делает его дочерним элементом

Возмножно стоит сделать класс ParameterStorage на основе ItemsControl и добавлять Parameter уже как дочерние элементы
Код

<my:ParameterStorage x:Name="myPS">
    <my:Parameter Value="{Binding PValue1}" />
    <my:Parameter Value="{Binding PValue1}" />
</my:ParameterStorage>

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)