Чтобы изменить второй столбец, вам нужно в какой-то момент получить индекс строки, которую нужно изменить. Я действительно не знаю библиотеку панд, но я могу дать вам решение:
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
Если вы создадите привязку в коде, то вы можете заставить его работать. Например, привязка, сгенерированная простым кодом:
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.
Я бы порекомендовал использовать конвертер:
<DataTemplate DataType={x:Type local:DummyClass}>
<TextBlock Text={Binding Converter={StaticResource PropertyNameToValueConverter, ConverterParameter=FieldValuePath}} />
</DataTemplate>
Преобразователь получит класс и имя свойства, и оттуда он вернет значение, используя отражение.
<DataTemplate DataType={x:Type local:DummyClass}>
<TextBlock Text={Binding Path=FieldValuePath} />
</DataTemplate>
Должен быть правильный метод. Если вы слушаете изменения в FieldValuePath, вам нужно убедиться, что DummyClass наследует от INotifyPropertyChanged и что событие измененного свойства запускается при изменении FieldValuePath.