WPF - 为触发器设置器设置 DataContext

发布于 2024-08-16 04:27:33 字数 7421 浏览 3 评论 0原文

我有一个最近重构的DataTrigger。它曾经将 DataContext 设置为 ListBoxItem。现在它是一个ContentPresenter

这是代码:

<DataTemplate.Triggers>
    <DataTrigger Value="True">
        <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
                <Binding ElementName="MainForm" Path="PickedWorkItemID"/>
                <Binding Path="WorkItemForColumn.Id"/>
            </MultiBinding>
        </DataTrigger.Binding>
        <Setter Property="IsEnabled" Value="False"/>
        <Setter Property="loc:Main.IsCurrentItemEnabledChanged" Value="True"/>
    </DataTrigger>
</DataTemplate.Triggers>

IsCurrentItemEnabledChangedOnChange 中,我可以看到我可以使用以下代码获取 ListBoxItem (在后面的代码中) ):

listBoxItem = (ListBoxItem)Main.Instance.lstQueryResults.ItemContainerGenerator.
               ContainerFromItem(((ContentPresenter)d).Content);

但是,我无法设置 DataContext,以便我的 IsEnabledSetter 将设置该对象的启用状态ListBoxItem 而不是 ContentPresenter

(我会在 IsCurrentItemEnabledChangedOnChange 中执行此操作,但该属性已经有点破解,当触发器设置为错误。)

有什么想法吗?


有人建议我提供更多内容来提供上下文:

这是我的模板 XAML。

<DataTemplate x:Key="ColumnTemplate">
    <Border Name="ItemBorder" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Padding="2">
        <WrapPanel>                   
            <TextBlock Margin="0,0,5,0">
                <TextBlock.Text>
                    <Binding Path="Name" Converter="{StaticResource GetVisibilityOfColumnTitles}"/>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock Text="{Binding Value}" Margin="0,0,10,0" FontWeight="Bold" />
        </WrapPanel>
    </Border>
</DataTemplate>

<DataTemplate x:Key="RowTemplate">
    <Border x:Name="ItemBorder" BorderThickness="1" BorderBrush="#D4D4FF">
        <Grid x:Name="ItemGrid" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsPresenter}}, Path=ActualWidth}" ScrollViewer.CanContentScroll="True" Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>
            <Grid.Background>
                <Binding Path="WorkItemForColumn.Type" Converter="{StaticResource WorkItemTypeToColorConverter}" />
            </Grid.Background>

            <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding
                                      RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
                                      Mode=TwoWay, Path=IsSelected}" Name="chkIsSelected" />

            <ItemsControl Grid.Column="1" Margin="5,0,5,0" ItemsSource="{Binding}" ItemTemplate="{StaticResource ColumnTemplate}" >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"></WrapPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>


            <Button HorizontalAlignment="Right" x:Name="btnPick" Grid.Column="3" Style="{StaticResource roundButton}" Width="15" Height="15" Tag="{Binding WorkItemForColumn.Id}" Margin="5,0,10,0">
                <Path Fill="DarkBlue">
                    <Path.Data>
                        <PathGeometry>
                            <PathFigure StartPoint="2,0" IsClosed="True">
                                <LineSegment Point="7,5"/>
                                <LineSegment Point="2,10"/>
                            </PathFigure>
                            <PathFigure StartPoint="2,2" IsClosed="True">
                                <LineSegment Point="5,5"/>
                                <LineSegment Point="2,8"/>
                            </PathFigure>
                        </PathGeometry>
                    </Path.Data>
                </Path>
            </Button>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
                    <Binding ElementName="MainForm" Path="PickedWorkItemID"/>
                    <Binding Path="WorkItemForColumn.Id"/>
                </MultiBinding>
            </DataTrigger.Binding>
            <Setter Property="IsEnabled" Value="False"/>
            <Setter Property="loc:Main.IsCurrentItemEnabledChanged" Value="True"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

下面是列表框的 XAML:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" Button.Click="PickWorkItem_Click" SelectionMode="Multiple" ItemTemplate="{StaticResource RowTemplate}"  Name="lstQueryResults" SelectionChanged="lstQueryResults_SelectionChanged" >
    <ListBox.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
            </Style.Resources>
        </Style>
    </ListBox.Resources>
</ListBox>

DataContext 在代码中设置如下:

private void ChangeQueryResultListSource(WorkItemCollection queryResults, bool b)
{
    // Un-hook the selection event while we change the ItemsSource
    Form.ToggleOnSelectEvent(false);

    // This sets the DataContext
    QueryDisplay = GetDisplayValues(queryResults);

    Form.QueryResultListSource = QueryDisplay;
    // Rewire the selection events back in
    Form.ToggleOnSelectEvent(true);


    foreach (WorkItem item in Pad.Keys)
    {
        Form.SelectQueryResultItem(item);
    }
}

private List<List<WorkItemColumn>> GetDisplayValues(WorkItemCollection queryResults)
{
    var result = new List<List<WorkItemColumn>>();
    foreach (WorkItem workItem in queryResults)
    {
        var row = GetQueryColumns(queryResults.DisplayFields, workItem);
        result.Add(row);
    }
    return result;
}

private List<WorkItemColumn> GetQueryColumns(DisplayFieldList fields, WorkItem workItem)
{
    var row = new List<WorkItemColumn>();
    foreach (FieldDefinition column in fields)
    {
        var workItemColumn = new WorkItemColumn { Name = column.Name, Value = workItem[column.Name], WorkItemForColumn = workItem };
        row.Add(workItemColumn);
    }

    return row;
}

WorkItemColumn 是一个具有名称-值对和对数据的引用的类(WorkItem代码>对象)。

I have a DataTrigger that I recently refactored. It used to have the DataContext set to be a ListBoxItem. Now it is a ContentPresenter.

Here is the code:

<DataTemplate.Triggers>
    <DataTrigger Value="True">
        <DataTrigger.Binding>
            <MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
                <Binding ElementName="MainForm" Path="PickedWorkItemID"/>
                <Binding Path="WorkItemForColumn.Id"/>
            </MultiBinding>
        </DataTrigger.Binding>
        <Setter Property="IsEnabled" Value="False"/>
        <Setter Property="loc:Main.IsCurrentItemEnabledChanged" Value="True"/>
    </DataTrigger>
</DataTemplate.Triggers>

In the OnChange of IsCurrentItemEnabledChanged I can see that I can get at the ListBoxItem with the following code (in the code behind):

listBoxItem = (ListBoxItem)Main.Instance.lstQueryResults.ItemContainerGenerator.
               ContainerFromItem(((ContentPresenter)d).Content);

However, there is no way that I can see to set the DataContext such that my Setter for IsEnabled will set the enabled status of the ListBoxItem rather than the ContentPresenter.

(I would do it in the OnChange of IsCurrentItemEnabledChanged, but that property is already a bit of a hack and it will not re-enable the item when the trigger is set to false.)

Any ideas?


It was suggested that I provide more to provide context:

Here is my XAML for the templates.

<DataTemplate x:Key="ColumnTemplate">
    <Border Name="ItemBorder" BorderBrush="Black" BorderThickness="1" CornerRadius="2" Padding="2">
        <WrapPanel>                   
            <TextBlock Margin="0,0,5,0">
                <TextBlock.Text>
                    <Binding Path="Name" Converter="{StaticResource GetVisibilityOfColumnTitles}"/>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock Text="{Binding Value}" Margin="0,0,10,0" FontWeight="Bold" />
        </WrapPanel>
    </Border>
</DataTemplate>

<DataTemplate x:Key="RowTemplate">
    <Border x:Name="ItemBorder" BorderThickness="1" BorderBrush="#D4D4FF">
        <Grid x:Name="ItemGrid" Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsPresenter}}, Path=ActualWidth}" ScrollViewer.CanContentScroll="True" Margin="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="30" />
            </Grid.ColumnDefinitions>
            <Grid.Background>
                <Binding Path="WorkItemForColumn.Type" Converter="{StaticResource WorkItemTypeToColorConverter}" />
            </Grid.Background>

            <CheckBox VerticalAlignment="Center" Grid.Column="0" IsChecked="{Binding
                                      RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}},
                                      Mode=TwoWay, Path=IsSelected}" Name="chkIsSelected" />

            <ItemsControl Grid.Column="1" Margin="5,0,5,0" ItemsSource="{Binding}" ItemTemplate="{StaticResource ColumnTemplate}" >
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal"></WrapPanel>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>


            <Button HorizontalAlignment="Right" x:Name="btnPick" Grid.Column="3" Style="{StaticResource roundButton}" Width="15" Height="15" Tag="{Binding WorkItemForColumn.Id}" Margin="5,0,10,0">
                <Path Fill="DarkBlue">
                    <Path.Data>
                        <PathGeometry>
                            <PathFigure StartPoint="2,0" IsClosed="True">
                                <LineSegment Point="7,5"/>
                                <LineSegment Point="2,10"/>
                            </PathFigure>
                            <PathFigure StartPoint="2,2" IsClosed="True">
                                <LineSegment Point="5,5"/>
                                <LineSegment Point="2,8"/>
                            </PathFigure>
                        </PathGeometry>
                    </Path.Data>
                </Path>
            </Button>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
                    <Binding ElementName="MainForm" Path="PickedWorkItemID"/>
                    <Binding Path="WorkItemForColumn.Id"/>
                </MultiBinding>
            </DataTrigger.Binding>
            <Setter Property="IsEnabled" Value="False"/>
            <Setter Property="loc:Main.IsCurrentItemEnabledChanged" Value="True"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

Here is the XAML for the List Box:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" Button.Click="PickWorkItem_Click" SelectionMode="Multiple" ItemTemplate="{StaticResource RowTemplate}"  Name="lstQueryResults" SelectionChanged="lstQueryResults_SelectionChanged" >
    <ListBox.Resources>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
            </Style.Resources>
        </Style>
    </ListBox.Resources>
</ListBox>

The DataContext is set in the Code like so:

private void ChangeQueryResultListSource(WorkItemCollection queryResults, bool b)
{
    // Un-hook the selection event while we change the ItemsSource
    Form.ToggleOnSelectEvent(false);

    // This sets the DataContext
    QueryDisplay = GetDisplayValues(queryResults);

    Form.QueryResultListSource = QueryDisplay;
    // Rewire the selection events back in
    Form.ToggleOnSelectEvent(true);


    foreach (WorkItem item in Pad.Keys)
    {
        Form.SelectQueryResultItem(item);
    }
}

private List<List<WorkItemColumn>> GetDisplayValues(WorkItemCollection queryResults)
{
    var result = new List<List<WorkItemColumn>>();
    foreach (WorkItem workItem in queryResults)
    {
        var row = GetQueryColumns(queryResults.DisplayFields, workItem);
        result.Add(row);
    }
    return result;
}

private List<WorkItemColumn> GetQueryColumns(DisplayFieldList fields, WorkItem workItem)
{
    var row = new List<WorkItemColumn>();
    foreach (FieldDefinition column in fields)
    {
        var workItemColumn = new WorkItemColumn { Name = column.Name, Value = workItem[column.Name], WorkItemForColumn = workItem };
        row.Add(workItemColumn);
    }

    return row;
}

WorkItemColumn is a class with a Name-Value pair and a reference to the data (a WorkItem object).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心舞飞扬 2024-08-23 04:27:33

抱歉,答案很简短,但您应该将 IsEnabled 的触发器和设置器逻辑移回 ListBoxItem 样式:

<Style TargetType="{x:Type ListBoxItem}">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
    </Style.Resources>
    <Style.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
                    <Binding ElementName="MainForm" Path="PickedWorkItemID"/>
                    <Binding Path="WorkItemForColumn.Id"/>
                </MultiBinding>
            </DataTrigger.Binding>
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

Sorry for the short answer, but you should move the trigger and setter logic for IsEnabled back to the ListBoxItem style:

<Style TargetType="{x:Type ListBoxItem}">
    <Style.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black"/>
        <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black"/>
    </Style.Resources>
    <Style.Triggers>
        <DataTrigger Value="True">
            <DataTrigger.Binding>
                <MultiBinding Converter="{StaticResource DisableWorkItemConverter}">
                    <Binding ElementName="MainForm" Path="PickedWorkItemID"/>
                    <Binding Path="WorkItemForColumn.Id"/>
                </MultiBinding>
            </DataTrigger.Binding>
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </Style.Triggers>
</Style>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文