Как я связываю Привязку. Свойство пути к базовым данным?

Чтобы изменить второй столбец, вам нужно в какой-то момент получить индекс строки, которую нужно изменить. Я действительно не знаю библиотеку панд, но я могу дать вам решение:

import pandas as pd
import collections

M = pd.DataFrame({'A': ['A12', 'A13', 'B54', 'B43', 'A43', 'A43'], 'B': ['A14', 'A22', 'A43', 'B52', 'B52', 'B53']}

output = pd.DataFrame(columns=['A', 'B'])

for i, c in collections.Counter(e).most_common():
    lines = M.loc[M['A']==i].index.values   # returns line indices
    for line in lines:
        output.loc[len(output)] = M.iloc[line]

И результат:

In [74]: output
Out[74]:
     A    B
0  A43  B52
1  A43  B53
2  A12  A14
3  A13  A22
4  B54  A43
5  B43  B52
7
задан arconaut 22 April 2009 в 17:03
поделиться

3 ответа

Если вы создадите привязку в коде, то вы можете заставить его работать. Например, привязка, сгенерированная простым кодом:

Binding binding = new Binding("BindingPath");
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(textBoxName, TextBox.TextProperty, binding);

Поскольку путь в этой привязке («BindingPath») является просто строкой, эта строка может быть получена из любого доступного объекта.

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


Еще одна возможность, основанная на ваших комментариях:

В этом сообщении в блоге описан способ создания настраиваемой привязки. Класс, наследуя от MarkupExtension. Возможно, вы сможете использовать это в качестве отправной точки, чтобы обернуть мое предложение в повторно используемую разметку xaml для вашего особого обязательного случая.


Больше мыслей:

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

Основываясь на своем решении на посте в блоге, на который я ссылался выше, я создал этот класс:

public class IndirectBinder : MarkupExtension
    {
        public string IndirectProperty { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            //try to get bound items for our custom work
            DependencyObject targetObject;
            DependencyProperty targetProperty;
            bool status = TryGetTargetItems(serviceProvider, out targetObject, out targetProperty);

            if (status)
            {
                Control targetControl = targetObject as Control;
                if (targetControl == null) return null;

                //Find the object to take the binding from
                object dataContext = targetControl.DataContext;
                if (dataContext == null) return null;

                //Reflect out the indirect property and get the value
                PropertyInfo pi = dataContext.GetType().GetProperty(IndirectProperty);
                if (pi == null) return null;

                string realProperty = pi.GetValue(dataContext, null) as string;
                if (realProperty == null) return null;

                //Create the binding against the inner property
                Binding binding = new Binding(realProperty);
                binding.Mode = BindingMode.TwoWay;
                BindingOperations.SetBinding(targetObject, targetProperty, binding);

                //Return the initial value of the binding
                PropertyInfo realPi = dataContext.GetType().GetProperty(realProperty);
                if (realPi == null) return null;

                return realPi.GetValue(dataContext, null);

            }

            return null;

        }

        protected virtual bool TryGetTargetItems(IServiceProvider provider, out DependencyObject target, out DependencyProperty dp)
        {
            target = null;
            dp = null;
            if (provider == null) return false;

            //create a binding and assign it to the target
            IProvideValueTarget service = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
            if (service == null) return false;

            //we need dependency objects / properties
            target = service.TargetObject as DependencyObject;
            dp = service.TargetProperty as DependencyProperty;
            return target != null && dp != null;
        }

Вы можете использовать эту новую разметку со следующим xaml:

<TextBox Text="{local:IndirectBinder IndirectProperty=FieldValuePath}"/>

Где TextBox может быть любым классом, который наследует от control, а Text может быть любым свойством зависимостей.

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

Хотя это и является сложным решением, у него есть одно преимущество перед использованием преобразователя, заключающееся в том, что окончательно созданная привязка направлена ​​против фактического внутреннего свойства, а не объекта. Это означает, что он правильно реагирует на события PropertyChanged.

public class IndirectBinder : MarkupExtension
    {
        public string IndirectProperty { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            //try to get bound items for our custom work
            DependencyObject targetObject;
            DependencyProperty targetProperty;
            bool status = TryGetTargetItems(serviceProvider, out targetObject, out targetProperty);

            if (status)
            {
                Control targetControl = targetObject as Control;
                if (targetControl == null) return null;

                //Find the object to take the binding from
                object dataContext = targetControl.DataContext;
                if (dataContext == null) return null;

                //Reflect out the indirect property and get the value
                PropertyInfo pi = dataContext.GetType().GetProperty(IndirectProperty);
                if (pi == null) return null;

                string realProperty = pi.GetValue(dataContext, null) as string;
                if (realProperty == null) return null;

                //Create the binding against the inner property
                Binding binding = new Binding(realProperty);
                binding.Mode = BindingMode.TwoWay;
                BindingOperations.SetBinding(targetObject, targetProperty, binding);

                //Return the initial value of the binding
                PropertyInfo realPi = dataContext.GetType().GetProperty(realProperty);
                if (realPi == null) return null;

                return realPi.GetValue(dataContext, null);

            }

            return null;

        }

        protected virtual bool TryGetTargetItems(IServiceProvider provider, out DependencyObject target, out DependencyProperty dp)
        {
            target = null;
            dp = null;
            if (provider == null) return false;

            //create a binding and assign it to the target
            IProvideValueTarget service = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
            if (service == null) return false;

            //we need dependency objects / properties
            target = service.TargetObject as DependencyObject;
            dp = service.TargetProperty as DependencyProperty;
            return target != null && dp != null;
        }

Вы можете использовать эту новую разметку со следующим xaml:

<TextBox Text="{local:IndirectBinder IndirectProperty=FieldValuePath}"/>

Где TextBox может быть любым классом, который наследует от control, а Text может быть любым свойством зависимости.

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

Хотя это сложное решение, одно из преимуществ, которое он имеет перед использованием конвертера, заключается в том, что окончательно созданное связывание является против фактического внутреннего свойства, а не объекта. Это означает, что он правильно реагирует на события PropertyChanged.

public class IndirectBinder : MarkupExtension
    {
        public string IndirectProperty { get; set; }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            //try to get bound items for our custom work
            DependencyObject targetObject;
            DependencyProperty targetProperty;
            bool status = TryGetTargetItems(serviceProvider, out targetObject, out targetProperty);

            if (status)
            {
                Control targetControl = targetObject as Control;
                if (targetControl == null) return null;

                //Find the object to take the binding from
                object dataContext = targetControl.DataContext;
                if (dataContext == null) return null;

                //Reflect out the indirect property and get the value
                PropertyInfo pi = dataContext.GetType().GetProperty(IndirectProperty);
                if (pi == null) return null;

                string realProperty = pi.GetValue(dataContext, null) as string;
                if (realProperty == null) return null;

                //Create the binding against the inner property
                Binding binding = new Binding(realProperty);
                binding.Mode = BindingMode.TwoWay;
                BindingOperations.SetBinding(targetObject, targetProperty, binding);

                //Return the initial value of the binding
                PropertyInfo realPi = dataContext.GetType().GetProperty(realProperty);
                if (realPi == null) return null;

                return realPi.GetValue(dataContext, null);

            }

            return null;

        }

        protected virtual bool TryGetTargetItems(IServiceProvider provider, out DependencyObject target, out DependencyProperty dp)
        {
            target = null;
            dp = null;
            if (provider == null) return false;

            //create a binding and assign it to the target
            IProvideValueTarget service = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget));
            if (service == null) return false;

            //we need dependency objects / properties
            target = service.TargetObject as DependencyObject;
            dp = service.TargetProperty as DependencyProperty;
            return target != null && dp != null;
        }

Вы можете использовать эту новую разметку со следующим xaml:

<TextBox Text="{local:IndirectBinder IndirectProperty=FieldValuePath}"/>

Где TextBox может быть любым классом, который наследует от control, а Text может быть любым свойством зависимости.

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

Хотя это сложное решение, одно из преимуществ, которое он имеет перед использованием конвертера, заключается в том, что окончательно созданное связывание является против фактического внутреннего свойства, а не объекта. Это означает, что он правильно реагирует на события PropertyChanged.

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

Хотя это сложное решение, одно из преимуществ которого заключается в том, что использование преобразователя заключается в том, что окончательно созданная привязка относится к фактическому внутреннему свойству, а не к объекту. Это означает, что он правильно реагирует на события PropertyChanged.

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

Хотя это сложное решение, одно из преимуществ которого заключается в том, что использование преобразователя заключается в том, что окончательно созданная привязка относится к фактическому внутреннему свойству, а не к объекту. Это означает, что он правильно реагирует на события PropertyChanged.

8
ответ дан 7 December 2019 в 01:26
поделиться

Я бы порекомендовал использовать конвертер:

 <DataTemplate DataType={x:Type local:DummyClass}>
    <TextBlock Text={Binding Converter={StaticResource PropertyNameToValueConverter, ConverterParameter=FieldValuePath}} />
 </DataTemplate>

Преобразователь получит класс и имя свойства, и оттуда он вернет значение, используя отражение.

2
ответ дан 7 December 2019 в 01:26
поделиться
<DataTemplate DataType={x:Type local:DummyClass}>
  <TextBlock Text={Binding Path=FieldValuePath} />
</DataTemplate>

Должен быть правильный метод. Если вы слушаете изменения в FieldValuePath, вам нужно убедиться, что DummyClass наследует от INotifyPropertyChanged и что событие измененного свойства запускается при изменении FieldValuePath.

0
ответ дан 7 December 2019 в 01:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: