所以我有这个程序,我主要使用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的东西,它有点可用。所以,如果它错了,请告诉我,然后将其删除。
要解释一下......在成品中,它将取决于我收到的数据,以决定是否有滑块或文本框。
只是我昨天提出的另一个问题的一个小例子:
答案 0 :(得分:2)
我看到您在Grid
中添加控件,手动生成行。虽然这当然可行,但使用列表控件并在其中创建项目会更好:
<ItemsControl ItemsSource="{x:Bind Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- your Sliders, etc. -->
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl>
如果数据可能在多个布局之间有所不同,您可以实现DataTemplateSelector
类,覆盖SelectTemplateCore(object item, DependencyObject container)
(具体来说,此方法还有另一个具有相同名称但参数数量不同的类别)没有调用)并决定每个项目的正确模板。您可以使用DataTemplates
创建多个x:Key
作为资源,然后从DataTemplateSelector
引用它们。有关示例,请参阅此blog post;有关详情,请参阅documentation。