使用数据绑定处理样式
Handling styling with data binding
重写
我有一个接收文件的应用程序。此文件包含大量可编辑内容。此内容有多种可能的类型(即布尔复选框、文本框等)。问题是,这些值可以是单独的,也可以是一组(最多 8 个),因此它们以数组的形式出现。我们将这些值绑定到一个 ListView
,并使用 DataTemplates
来显示它们。实际上,我从数组列表中创建了 ListView
。
这些数组中的项目需要进行数据绑定并正确设置样式(例如,布尔数组需要创建复选框,而字符串数组需要文本框)。每个创建的元素都需要放入 ListView
中的一列中。当前样式使用 DataTemplates
和数据绑定,即
<DataTemplate x:Key="testTemplate2">
<TextBlock Text="{Binding Path=Value[0]}"
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DataTemplate>
对输入数组中的每个值重复此操作,因此您有 Value[1]
、Value[2]
等
这意味着将几乎相同的代码重复 8 次,然后对下一种类型执行相同的操作。由于有大量的输入类型,这意味着大量的重复代码。
我的问题是:有没有更好的方法来做到这一点,这样我们就不必重复数据模板,同时继续使用列?
顺便说一下,我正在使用 .NET 3.5。
行的外观示例。每个元素都在其自己的列中。组合框是从数组构建的。
编辑
示例数据模板:
<DataTemplate x:Key="textBoxTemplate2">
<TextBox Text="{Binding Path=Value[2], NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
BorderBrush="{DynamicResource ComboBorder}"
Tag="{Binding Path=AllowedChars}"
PreviewTextInput="PreviewTextInputHandler"
DataObject.Pasting="PastingHandler"
ToolTip="{Binding Path=Title}"
Margin="2"
SourceUpdated="BindingSourceUpdated"
MaxLength="{Binding Path=DataLength}"
HorizontalAlignment="Stretch"
VerticalAlignment="Center" >
<TextBox.IsEnabled>
<MultiBinding Converter="{StaticResource isEnabledConverter}">
<Binding Path="IsLocked" Mode="OneWay" />
<Binding Path="IsVisible[2]" Mode="OneWay" />
</MultiBinding>
</TextBox.IsEnabled>
</TextBox>
</DataTemplate>
示例图:
我有一个 ViewModel。这个 ViewModel 有一个列表,由 ItemData 组成。 Class ItemData 有一个名为 Values 的数组。列表绑定到视图。我们需要根据我们正在访问的 属性 的 ItemData 选择要使用的 DataTemplate:
- 一个名字
- 一个或多个选项数组。
目前,我们在 ListView 中显示 List。生成 ListView
时,列的 CellTemplate
附加了不同的 DataTemplates
,每个索引一个,总共 8 个数据模板。
我的回答主要集中在你的话上:由于有大量的输入类型,这意味着大量的重复代码。
代码重用:
由于您在Item template
中需要为不同的DataTypes
定义不同类型的控件,因此无法完全减少代码。我的意思是,如果您想要 TextBox
用于 String
类型或 Checkbox
用于 Bool
类型,则代码不能明显减少。但是,您可以减少的是为不同的 template
一次又一次地定义 Binding
语法,正如我在您的 TextBox
Template
示例中看到的那样。您可以定义 Biniding
一次,然后使用 n 个控件(在您的情况下为 8 个)一次又一次地重复使用它们。以下是您的操作方法:
public class BindingResourceExtension : StaticResourceExtension
{
public BindingResourceExtension() : base() { }
public BindingResourceExtension(object resourceKey) : base(resourceKey) { }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = base.ProvideValue(serviceProvider) as BindingBase;
if (binding != null)
return binding.ProvideValue(serviceProvider);
else
return null; //or throw an exception
}
}
XAML
<Window.Resources>
<ResourceDictionary>
<Binding x:Key="MyBinding" Path="MyProperty" Mode="TwoWay" />
</ResourceDictionary>
</Window.Resources>
(...)
<TextBox Text="{ns:BindingResource MyBinding}" />
<CheckBox IsChecked="{ns:BindingResource MyBinding}" />
因此可以实现一些代码的重用(想象一下上面的代码又大又复杂bindings
)。在您发布您的问题后,我正在搜索类似的内容,所以我发布了另一个 并且它有所帮助。此外,由于 Bindings
将集中化,它们将很容易更新。
项目模板:
除了您的代码重用问题之外,您还可以使用嵌套的 ItemsControl
,因为我可以看到您的 class 图,并且在另一个答案中也有建议:
<ListBox ItemsSource="{Binding CollectionOfArrays}">
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Array}" />
</DataTemplate>
</ListBox.ItemTemplate>
现在对于内部 ItemsControl
你必须实际定义 Templates
,但我认为你已经清楚了那部分。
重写
我有一个接收文件的应用程序。此文件包含大量可编辑内容。此内容有多种可能的类型(即布尔复选框、文本框等)。问题是,这些值可以是单独的,也可以是一组(最多 8 个),因此它们以数组的形式出现。我们将这些值绑定到一个 ListView
,并使用 DataTemplates
来显示它们。实际上,我从数组列表中创建了 ListView
。
这些数组中的项目需要进行数据绑定并正确设置样式(例如,布尔数组需要创建复选框,而字符串数组需要文本框)。每个创建的元素都需要放入 ListView
中的一列中。当前样式使用 DataTemplates
和数据绑定,即
<DataTemplate x:Key="testTemplate2">
<TextBlock Text="{Binding Path=Value[0]}"
Margin="2"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DataTemplate>
对输入数组中的每个值重复此操作,因此您有 Value[1]
、Value[2]
等
这意味着将几乎相同的代码重复 8 次,然后对下一种类型执行相同的操作。由于有大量的输入类型,这意味着大量的重复代码。
我的问题是:有没有更好的方法来做到这一点,这样我们就不必重复数据模板,同时继续使用列?
顺便说一下,我正在使用 .NET 3.5。
行的外观示例。每个元素都在其自己的列中。组合框是从数组构建的。
编辑 示例数据模板:
<DataTemplate x:Key="textBoxTemplate2">
<TextBox Text="{Binding Path=Value[2], NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}"
BorderBrush="{DynamicResource ComboBorder}"
Tag="{Binding Path=AllowedChars}"
PreviewTextInput="PreviewTextInputHandler"
DataObject.Pasting="PastingHandler"
ToolTip="{Binding Path=Title}"
Margin="2"
SourceUpdated="BindingSourceUpdated"
MaxLength="{Binding Path=DataLength}"
HorizontalAlignment="Stretch"
VerticalAlignment="Center" >
<TextBox.IsEnabled>
<MultiBinding Converter="{StaticResource isEnabledConverter}">
<Binding Path="IsLocked" Mode="OneWay" />
<Binding Path="IsVisible[2]" Mode="OneWay" />
</MultiBinding>
</TextBox.IsEnabled>
</TextBox>
</DataTemplate>
示例图:
我有一个 ViewModel。这个 ViewModel 有一个列表,由 ItemData 组成。 Class ItemData 有一个名为 Values 的数组。列表绑定到视图。我们需要根据我们正在访问的 属性 的 ItemData 选择要使用的 DataTemplate:
- 一个名字
- 一个或多个选项数组。
目前,我们在 ListView 中显示 List。生成 ListView
时,列的 CellTemplate
附加了不同的 DataTemplates
,每个索引一个,总共 8 个数据模板。
我的回答主要集中在你的话上:由于有大量的输入类型,这意味着大量的重复代码。
代码重用:
由于您在Item template
中需要为不同的DataTypes
定义不同类型的控件,因此无法完全减少代码。我的意思是,如果您想要 TextBox
用于 String
类型或 Checkbox
用于 Bool
类型,则代码不能明显减少。但是,您可以减少的是为不同的 template
一次又一次地定义 Binding
语法,正如我在您的 TextBox
Template
示例中看到的那样。您可以定义 Biniding
一次,然后使用 n 个控件(在您的情况下为 8 个)一次又一次地重复使用它们。以下是您的操作方法:
public class BindingResourceExtension : StaticResourceExtension
{
public BindingResourceExtension() : base() { }
public BindingResourceExtension(object resourceKey) : base(resourceKey) { }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var binding = base.ProvideValue(serviceProvider) as BindingBase;
if (binding != null)
return binding.ProvideValue(serviceProvider);
else
return null; //or throw an exception
}
}
XAML
<Window.Resources>
<ResourceDictionary>
<Binding x:Key="MyBinding" Path="MyProperty" Mode="TwoWay" />
</ResourceDictionary>
</Window.Resources>
(...)
<TextBox Text="{ns:BindingResource MyBinding}" />
<CheckBox IsChecked="{ns:BindingResource MyBinding}" />
因此可以实现一些代码的重用(想象一下上面的代码又大又复杂bindings
)。在您发布您的问题后,我正在搜索类似的内容,所以我发布了另一个 Bindings
将集中化,它们将很容易更新。
项目模板:
除了您的代码重用问题之外,您还可以使用嵌套的 ItemsControl
,因为我可以看到您的 class 图,并且在另一个答案中也有建议:
<ListBox ItemsSource="{Binding CollectionOfArrays}">
<ListBox.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Array}" />
</DataTemplate>
</ListBox.ItemTemplate>
现在对于内部 ItemsControl
你必须实际定义 Templates
,但我认为你已经清楚了那部分。