У меня есть два текстовых поля, которые мне нужно найти в сетке WPF. Я нашел их обоих. Затем я привязываю текстовые поля к свойствам класса, который использует INotifyPropertyChanged. Первое текстовое поле привязывается правильно. Второй нет. Я попытался создать новое второе текстовое поле и привязать его к исходному свойству второго текстового поля. Теперь я получаю сообщение об ошибке «Привязка не может быть изменена после ее использования». Я попытался очистить привязку с помощью «BindingOperations.ClearAllBindings(textBox02)», но все равно получаю ошибку. Я удалил второе текстовое поле и создал другое. Один раз запустилось без ошибки, а потом ошибка появилась снова.
Как добавить IValueConverter к существующей привязке
имеет ту же проблему. Я попытался создать новую привязку, но при втором запуске получил ту же ошибку.
Я новичок в ВПП. Я не знаю, говорит ли мне ошибка о том, что мне нужно использовать новую привязку, привязку к другому свойству или заменить текстовое поле. Я попробовал все три, но проблема осталась. Коды для различных областей приведены ниже.
Заранее спасибо,
Род Маккей
Создайте текстовые поля:
chartTraderCustomTextBlockArray[1] = new TextBlock()
{
FontFamily = ChartControl.Properties.LabelFont.Family,
FontSize = 13,
Foreground = ChartControl.Properties.ChartText,
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(5, 20, 5, 5),
Name = "txtBlock01",
Text = string.Format("{0} ", indicatorRiskValue)
};
chartTraderCustomTextBoxArray[0] = new TextBox()
{
FontFamily = ChartControl.Properties.LabelFont.Family,
FontSize = 13,
Foreground = ChartControl.Properties.ChartText,
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(5, 5, 5, 5),
Name = "textBox02",
Text = string.Format("{0} ", shareQuantity),
Height = 20,
Width = 240
};
Я использовал следующий код, чтобы найти текстовые поля:
chartWindow = System.Windows.Window.GetWindow(e.Parent) as NinjaTrader.Gui.Chart.Chart;
chartTraderGrid = (chartWindow.FindFirst("ChartWindowChartTraderControl") as ChartTrader).Content as Grid;
textBox00 = chartTraderGrid.FindFirst("TextBox00") as System.Windows.Controls.TextBox;
textBox02 = chartTraderGrid.FindFirst("TextBox02") as System.Windows.Controls.TextBox;
Ящики найдены правильно. Затем я привязываю текстовые поля к свойствам в классе, который использует INotifyPropertyChanged.
Binding binding = new Binding("Quantity");
binding.Source = noOfShares;
textBox00.SetBinding(TextBox.TextProperty, binding)
Binding binding2 = new Binding("Risk");
binding.Source = noOfShares;
textBox02.SetBinding(TextBox.TextProperty, binding2);
Это источник привязки:
public class NumberOfShares : ObservableObject
{
private string _risk;
private string _quantity;
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
public NumberOfShares()
{
}
public string Risk
{
get { return _risk; }
set
{
_risk = value;
OnPropertyChanged();
}
}
public string Quantity
{
get { return _quantity; }
set
{
_quantity = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged();
}
}
// Create the OnPropertyChanged method to raise the event
// The calling member's name will be used as the parameter.
protected void OnPropertyChanged([CallerMemberName] string quantity = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(quantity));
}
}
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyname = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
}
Для каждого использования Binding создает неизменяемый экземпляр BindingExpression, который является фактическим базовым объектом привязки, управляющим соединением между двумя объектами. Если бы вам было разрешено изменять используемую привязку, то платформе также пришлось бы изменить все связанные с ней выражения BindingExpressions. Это может привести к потенциально нежелательным побочным эффектам. Потому что эта модификация изменит ВСЕ привязки, а не только привязку конкретного целевого элемента, который вы хотели изменить. Перфоманс, вероятно, тоже был на уме у автора. Почему это так, мы можем только догадываться.
С технической точки зрения более важным является тот факт, что BindingExpression является неизменным и что ассоциации не отслеживаются (Binding не запоминает и не наблюдает за всеми созданными им BindingExpressions).
Возможно, вместо изменения привязки вам следует изменить значение исходного свойства. Это намного проще и эффективнее, чем изменение/замена привязки.
Я думаю, что у вас просто случайная ошибка при наборе текста. Правильно было бы:
Binding binding = new Binding("Quantity");
binding.Source = noOfShares;
textBox00.SetBinding(TextBox.TextProperty, binding)
Binding binding2 = new Binding("Risk");
// binding.Source = noOfShares; Invalid line
binding2.Source = noOfShares; // Correct variant
textBox02.SetBinding(TextBox.TextProperty, binding2);
Чтобы избежать подобных ошибок, используйте инициализаторы:
Binding binding = new Binding("Quantity")
{
Source = noOfShares
};
textBox00.SetBinding(TextBox.TextProperty, binding)
Binding binding2 = new Binding("Risk")
{
Source = noOfShares
};
textBox02.SetBinding(TextBox.TextProperty, binding2);
Бионический код. Спасибо за объяснение. Я искал везде, о чем только мог подумать, и ваш ответ, наконец, объясняет процесс привязки до такой степени, что я понимаю. EldHasp Тут немного смутился. Я продолжал искать логическую ошибку, и это была опечатка. Спасибо
Отличные глаза... ;)
А где код, изменяющий существующую привязку? Похоже, вы не опубликовали полный соответствующий код. Если вы хотите изменить объект Binding, вы должны клонировать его (или просто создать новый экземпляр) и переназначить его. Изменение существующей привязки не допускается, поскольку она запечатывается, как только ей присваивается целевое свойство. Идея состоит в том, что вы можете использовать один экземпляр Binding для установки нескольких привязок.