我在Window.Resources
:
<Window.Resources>
<ValueConverters:StudyPointWorkingOn x:Key="StudyPointWorkingOn" />
<Style x:Key="StudyPointComboBoxStyle" TargetType="ComboBoxItem">
<Setter Property="Tag" Value="{Binding Number}" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
<Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
<Binding Path="DataContext.SelectedStudentItem" ElementName="oclmEditor" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="StudyPointComboItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
在我的MainWindow
代码中,我有几个地方使用上述资源。这是一个例子:
<StackPanel>
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding NumberClasses, ConverterParameter=1, Converter={StaticResource IsEqualOrGreaterThanConverter}}" Value="True">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Label Content="Student:"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="textBibleReadingMain" Grid.Column="0" Margin="2" IsEnabled="False"
Text="{Binding BibleReadingMainName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
<Button x:Name="buttonBibleReadingMain" Grid.Column="1" Background="Transparent"
DataContext="{Binding DataContext, ElementName=oclmEditor}"
Command="{Binding ApplicationCommand}" CommandParameter="BibleReadingMain">
<Image Source="Images/AssignmentTypeBibleReading16.png" Margin="2"/>
</Button>
</Grid>
<Label Content="Study:"/>
<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
ItemsSource="{Binding ReadingStudyPointsList}"
ItemContainerStyle="{StaticResource StudyPointComboBoxStyle}"
ItemTemplate="{StaticResource StudyPointComboItem}"/>
</StackPanel>
我已将其纳入上下文以显示我的问题。首先,我必须指出它的工作原理。我现在遇到的问题是因为我想略微改变逻辑。
通过几个控件查看TextBox
之前的ComboBox
对象:
<TextBox x:Name="textBibleReadingMain" Grid.Column="0" Margin="2" IsEnabled="False"
Text="{Binding BibleReadingMainName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
如果可能,我想将Text值BibleReadingMainName
作为MultiBinding对象中的参数传递。但它很复杂,因为我有几个地方,我有这种风格:
[Text][Button]
[Label]
[Combo]
因此,在每个实例中,[Text]元素具有不同的名称,并且关联的属性将不同。有什么方法我仍然可以使用一个资源,但以某种方式通过TextBox.Text
或适当的Property
?我知道我可以使用RelativeSource
,但这是为了寻找祖先,这更像是一个侄子... :)
谢谢你提供的答案到目前为止。请允许我向您展示我所做的工作,因为我不能尚完全看到如何实现这一点,因为您建议ViewModel
。
我调整了Windows.Resources
<Style x:Key="StudyPointComboBoxStyle" TargetType="ComboBoxItem">
<Setter Property="Tag" Value="{Binding Number}" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
<Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
<Binding Path="DataContext" ElementName="oclmEditor" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="Tag" RelativeSource="{RelativeSource AncestorType=ComboBox}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="StudyPointComboItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Title}"/>
</StackPanel>
</DataTemplate>
如您所见,我现在也传递了ComboBox
Tag
属性。
我的各种ComboBox控件现在定义如下(其中3个显示):
如您所见,每个ComboBox
将其Tag
设置为ViewModel
中的相应属性(随后连接到它自己的TextBox)。
Converter
方法现在看起来像这样:
命名空间OCLMEditor.ValueConverters { class StudyPointWorkingOn:IMultiValueConverter { public object Convert(object [] values,Type targetType,object parameter,CultureInfo culture) { int iStudyNumber =(int)values [0]; OCLMEditorViewModel vm =(OCLMEditorViewModel)值[1]; string strStudent =(string)values [2];
if (vm != null && strStudent != null)
{
Student oStudent = vm.FindStudent(strStudent);
if (oStudent != null && oStudent.IsWorkingOnStudyPoint(iStudyNumber))
return true;
}
return false;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
最后,我必须向ViewModel添加一个公共包装器方法:
public Student FindStudent(string strStudent) { return _Model.FindStudent(strStudent); }
上述方法对我有用。但提供的答案是使用ViewModel
来包装StudyPointItem
和关联的Name
属性。我无法完全看到提议的代码如何反映上述工作流程。
答案 0 :(得分:2)
IMO,我会以某种方式将必要的信息传递给您绑定的每个项目,而不是查找通过控件树导航的信息。因此,我认为它更易于维护,因为如果布局发生更改,则不必更新绑定。
在您的情况下,组合框的每个项目的DataContext是ReadingStudyPointsList的每个元素。因此,当您创建传递“this”实例的元素以访问ViewModel的每个属性时,您可以传递对具有BibleReadingMainName的实际ViewModel的引用,例如:
this.ReadingStudyPointsList.Add(new ReadingStudyPointItemViewModel(this, other parameters))
那么在您的ReadingStudyPointItemViewModel中,您可以拥有一个属性,该属性包含在ctor中分配的父ViewModel以访问您需要的信息:
public ParentViewModel ParentVM { get; set; }
最后,您的绑定将变为:
<Style x:Key="StudyPointComboBoxStyle" TargetType="ComboBoxItem">
<Setter Property="Tag" Value="{Binding Number}" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
<Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
<Binding Path="DataContext.SelectedStudentItem" ElementName="oclmEditor" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="DataContext.ParentVM.BibleReadingMainName" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
我希望这适合你。