从代码隐藏文件设置绑定时绑定源不会更改
Binding source doesn't change when setting the binding from code behind file
所以我有这个程序,我主要通过使用 x:Bind
来完成所有绑定,但我有一个控制页面,我需要在其中生成大量 Slider
才能操作数据我存储在 ObservableCollection<T>
我真的需要从我的代码中生成这些滑块,因为我需要大约 100 个滑块,如果手动创建它们会弄乱我的 xmal 文件...
这就是我在代码中创建绑定的方式。当我第一次加载它们时,它们也会工作。但是当我移动滑块时它们不会更改源数据。
private void CreateGrid()
{
for (var parameterNumberIndex = 1; parameterNumberIndex < 97; parameterNumberIndex++)
{
var paraName = new TextBlock()
{
Name = $"Parameter{parameterNumberIndex}",
FontSize = 25,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(0, 0, 0, 10)
};
var slider = new Slider()
{
Name = $"ValueSlider{parameterNumberIndex}",
Width = 200,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
var value = new TextBox()
{
Name = $"ValueBox{parameterNumberIndex}",
Margin = new Thickness(10, 5, 0, 0),
FontSize = 20,
VerticalAlignment = VerticalAlignment.Top
};
var row = new RowDefinition { Height = new GridLength(50, GridUnitType.Pixel) };
SettingsGrid.RowDefinitions.Add(row);
var nameBinding = new Binding
{
Source = ViewModel.BlockCollection.NamesBlock.Names[parameterNumberIndex].NameString,
Mode = BindingMode.OneWay
};
var valueBinding = new Binding()
{
Source = ViewModel.BlockCollection.ParameterBlock.Parameters[parameterNumberIndex].ParameterValue,
Mode = BindingMode.TwoWay
};
var minBinding = new Binding()
{
Source = ViewModel.BlockCollection.MinMaxBlock.AllValues[parameterNumberIndex].MinValue,
Mode = BindingMode.OneWay
};
var maxBinding = new Binding()
{
Source = ViewModel.BlockCollection.MinMaxBlock.AllValues[parameterNumberIndex].MaxValue,
Mode = BindingMode.OneWay
};
var textBinding = new Binding()
{
Path = new PropertyPath("Value"),
Source = slider,
Mode = BindingMode.TwoWay
};
BindingOperations.SetBinding(paraName, TextBlock.TextProperty, nameBinding);
BindingOperations.SetBinding(slider, Slider.MinimumProperty, minBinding);
BindingOperations.SetBinding(slider, Slider.MaximumProperty, maxBinding);
BindingOperations.SetBinding(slider, Slider.ValueProperty, valueBinding);
BindingOperations.SetBinding(value, TextBox.TextProperty, textBinding);
SettingsGrid.Children.Add(paraName);
SettingsGrid.Children.Add(slider);
SettingsGrid.Children.Add(value);
Grid.SetColumn(paraName, 0);
Grid.SetColumn(slider, 1);
Grid.SetColumn(value, 2);
Grid.SetRow(paraName, parameterNumberIndex - 1);
Grid.SetRow(slider, parameterNumberIndex - 1);
Grid.SetRow(value, parameterNumberIndex - 1);
}
}
Source = ...
总是 ObservableCollection<T>
取决于我需要它们的类型。
滑块源是 uint
的集合。
BindableBase
是我实现的INotifyPropertyChanged
。
public class ParameterBlock : BindableBase
{
public ParameterBlock()
{
this.Parameters = new ObservableRangeCollection<ParameterBlockValue>();
}
public ObservableRangeCollection<ParameterBlockValue> Parameters
{
get => _parameters;
set
{
_parameters = value;
OnPropertyChanged();
}
}
private ObservableRangeCollection<ParameterBlockValue> _parameters;
}
public class ParameterBlockValue : BindableBase
{
private uint _parameterValue;
public uint ParameterValue
{
get => _parameterValue;
set
{
_parameterValue = value;
OnPropertyChanged();
}
}
public ParameterBlockValue(uint parameter)
{
this.ParameterValue = parameter;
}
public override string ToString()
{
return $"{this.ParameterValue} {Environment.NewLine}";
}
}
这几乎是我或多或少完成这个项目之前需要修复的最后一步,我不想卡在这里:/
不知道是不是wpf标签写错了。但每次我寻找 xaml 参考时,我都会无意中发现 wpf 的东西,它有点用。所以如果有错请告诉我,我会删除它。
再解释一下...在成品中,将取决于我收到的数据来决定是否会有滑块或文本框。
只是我昨天遇到的另一个问题的一个小示例图片:
我看到您在 Grid
中添加控件,手动生成行。虽然这当然可行,但最好使用列表控件并在以下范围内创建项目:
<ItemsControl ItemsSource="{x:Bind Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- your Sliders, etc. -->
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl>
如果多个布局之间的数据可能不同,您可以实现 DataTemplateSelector
class,覆盖 SelectTemplateCore(object item, DependencyObject container)
(具体来说,还有另一个同名但不同数量的未调用的参数)并为每个项目决定正确的模板。您可以使用 x:Key
创建多个 DataTemplates
作为资源,然后从您的 DataTemplateSelector
引用它们。有关详细信息,请参阅此 blog post for an example and documentation。
所以我有这个程序,我主要通过使用 x:Bind
来完成所有绑定,但我有一个控制页面,我需要在其中生成大量 Slider
才能操作数据我存储在 ObservableCollection<T>
我真的需要从我的代码中生成这些滑块,因为我需要大约 100 个滑块,如果手动创建它们会弄乱我的 xmal 文件...
这就是我在代码中创建绑定的方式。当我第一次加载它们时,它们也会工作。但是当我移动滑块时它们不会更改源数据。
private void CreateGrid()
{
for (var parameterNumberIndex = 1; parameterNumberIndex < 97; parameterNumberIndex++)
{
var paraName = new TextBlock()
{
Name = $"Parameter{parameterNumberIndex}",
FontSize = 25,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(0, 0, 0, 10)
};
var slider = new Slider()
{
Name = $"ValueSlider{parameterNumberIndex}",
Width = 200,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
var value = new TextBox()
{
Name = $"ValueBox{parameterNumberIndex}",
Margin = new Thickness(10, 5, 0, 0),
FontSize = 20,
VerticalAlignment = VerticalAlignment.Top
};
var row = new RowDefinition { Height = new GridLength(50, GridUnitType.Pixel) };
SettingsGrid.RowDefinitions.Add(row);
var nameBinding = new Binding
{
Source = ViewModel.BlockCollection.NamesBlock.Names[parameterNumberIndex].NameString,
Mode = BindingMode.OneWay
};
var valueBinding = new Binding()
{
Source = ViewModel.BlockCollection.ParameterBlock.Parameters[parameterNumberIndex].ParameterValue,
Mode = BindingMode.TwoWay
};
var minBinding = new Binding()
{
Source = ViewModel.BlockCollection.MinMaxBlock.AllValues[parameterNumberIndex].MinValue,
Mode = BindingMode.OneWay
};
var maxBinding = new Binding()
{
Source = ViewModel.BlockCollection.MinMaxBlock.AllValues[parameterNumberIndex].MaxValue,
Mode = BindingMode.OneWay
};
var textBinding = new Binding()
{
Path = new PropertyPath("Value"),
Source = slider,
Mode = BindingMode.TwoWay
};
BindingOperations.SetBinding(paraName, TextBlock.TextProperty, nameBinding);
BindingOperations.SetBinding(slider, Slider.MinimumProperty, minBinding);
BindingOperations.SetBinding(slider, Slider.MaximumProperty, maxBinding);
BindingOperations.SetBinding(slider, Slider.ValueProperty, valueBinding);
BindingOperations.SetBinding(value, TextBox.TextProperty, textBinding);
SettingsGrid.Children.Add(paraName);
SettingsGrid.Children.Add(slider);
SettingsGrid.Children.Add(value);
Grid.SetColumn(paraName, 0);
Grid.SetColumn(slider, 1);
Grid.SetColumn(value, 2);
Grid.SetRow(paraName, parameterNumberIndex - 1);
Grid.SetRow(slider, parameterNumberIndex - 1);
Grid.SetRow(value, parameterNumberIndex - 1);
}
}
Source = ...
总是 ObservableCollection<T>
取决于我需要它们的类型。
滑块源是 uint
的集合。
BindableBase
是我实现的INotifyPropertyChanged
。
public class ParameterBlock : BindableBase
{
public ParameterBlock()
{
this.Parameters = new ObservableRangeCollection<ParameterBlockValue>();
}
public ObservableRangeCollection<ParameterBlockValue> Parameters
{
get => _parameters;
set
{
_parameters = value;
OnPropertyChanged();
}
}
private ObservableRangeCollection<ParameterBlockValue> _parameters;
}
public class ParameterBlockValue : BindableBase
{
private uint _parameterValue;
public uint ParameterValue
{
get => _parameterValue;
set
{
_parameterValue = value;
OnPropertyChanged();
}
}
public ParameterBlockValue(uint parameter)
{
this.ParameterValue = parameter;
}
public override string ToString()
{
return $"{this.ParameterValue} {Environment.NewLine}";
}
}
这几乎是我或多或少完成这个项目之前需要修复的最后一步,我不想卡在这里:/
不知道是不是wpf标签写错了。但每次我寻找 xaml 参考时,我都会无意中发现 wpf 的东西,它有点用。所以如果有错请告诉我,我会删除它。
再解释一下...在成品中,将取决于我收到的数据来决定是否会有滑块或文本框。
只是我昨天遇到的另一个问题的一个小示例图片:
我看到您在 Grid
中添加控件,手动生成行。虽然这当然可行,但最好使用列表控件并在以下范围内创建项目:
<ItemsControl ItemsSource="{x:Bind Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- your Sliders, etc. -->
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl>
如果多个布局之间的数据可能不同,您可以实现 DataTemplateSelector
class,覆盖 SelectTemplateCore(object item, DependencyObject container)
(具体来说,还有另一个同名但不同数量的未调用的参数)并为每个项目决定正确的模板。您可以使用 x:Key
创建多个 DataTemplates
作为资源,然后从您的 DataTemplateSelector
引用它们。有关详细信息,请参阅此 blog post for an example and documentation。