5

データグリッドにチェックボックスの列があります。

<DataGridTemplateColumn CanUserResize="False" Header="" Width="auto">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <CheckBox Style="{StaticResource CheckBoxSelectTypeStyle}" IsChecked="{Binding Path=Selected}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

チェックの解除とチェックにバインドされたコマンドがあります。

<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="HorizontalAlignment" Value="Center" />
    <Setter Property="VerticalAlignment" Value="Center" />
    <Style.Triggers>
        <Trigger Property="IsChecked" Value="True">
            <Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
            <Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
        </Trigger>
        <Trigger Property="IsChecked" Value="False">
            <Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
            <Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
        </Trigger>
    </Style.Triggers>
</Style>

私の問題は、チェックボックスがチェックされていない状態で開始し、チェックボックスをオンにすると、コマンドが起動されないことです(これが問題です)。その後、同じチェックボックスのチェックを外すと、uncheck コマンドが起動します (期待どおり)。その後、同じチェックボックスを再度オンにすると、チェック コマンドが実行されます (予想どおり)。その時点でそのチェックボックスはすべて正常に機能しますが、他のチェックボックスにはまだ同じ問題があります。

チェックボックスがオンになっている場合は、正常に機能します。私の質問は、チェックボックスがオフになっているときにコマンドを起動する方法です。うまくいかない理由が見つかりません。

提案への応答:

のトリガーを追加しようとしましNullたが、まったく同じ問題があり、何も変わりませんでした。

<Style.Triggers>
    <Trigger Property="IsChecked" Value="True">
        <Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
        <Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
    </Trigger>
    <Trigger Property="IsChecked" Value="False">
        <Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
        <Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
    </Trigger>
    <Trigger Property="IsChecked" Value="{x:Null}">
        <Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
        <Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
    </Trigger>
</Style.Triggers>

ViewModel コード

public ICommand CheckedCommand { get; set; }
public ICommand UncheckedCommand { get; set; }

CheckedCommand = new RelayCommand<IList>(Checked);
UncheckedCommand = new RelayCommand<IList>(Unchecked);

private void Checked(IList selectedItems)
{
    ChangedChecked(selectedItems, true);
}

private void Unchecked(IList selectedItems)
{
    ChangedChecked(selectedItems, false);
}

private void ChangedChecked(IList selectedItems, bool selected)
{
    if (selectedItems.HasValue())
        foreach (var item in selectedItems)
            if(item is SelectedTypeModel) (item as SelectedTypeModel).Selected = selected;
}

RelayCommand は ICommand を実装します。前に述べたようにChecked、チェックボックスがチェックされていない状態で開始された場合、このメソッドは呼び出されませんが、チェックされ、チェック解除され、再度チェックされた場合、またはチェックされて開始され、チェックされていない場合に呼び出されます。

私がやろうとしていること

CheckBox の列を持つ DataGrid があります。複数の行を強調表示してから、選択した行のいずれかで CheckBox をオン/オフにして、他のすべての行を同じになるように更新できるようにしたいと考えています。また、データ グリッドのキーワード フィルターがあるため、DataGrid は ListCollectionView にバインドされます。

出力情報

データ バインディングのデバッグ情報を有効にすると、次のメッセージが表示されます。

System.Windows.Data 情報: 10 : バインディングを使用して値を取得できず、有効なフォールバック値が存在しません。代わりにデフォルトを使用します。BindingExpression: パス = 選択; DataItem=null; ターゲット要素は 'CheckBox' (Name='') です。ターゲット プロパティは 'IsChecked' (タイプ 'Nullable`1') です

ただし、この情報を使用して問題を修正する方法はまだわかりません。

解決

元の問題は解決していませんが、なぜ正しく機能しないのかはまだわかりませんが、別の方法を使用しても同じ結果が得られました。変更されたコードは次のとおりです。

<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="Command" Value="{Binding DataContext.CheckedChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    <Setter Property="CommandParameter">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource SelectedItemsCheckedMultiValueConverter}">
                <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}" Path="SelectedItems"/>
                <Binding RelativeSource="{RelativeSource Self}" Path="IsChecked"/>
            </MultiBinding>
        </Setter.Value>
    </Setter>
</Style>

public ICommand CheckedChangedCommand { get; set; }

CheckedChangedCommand = new RelayCommand<Tuple<IList, bool>>(CheckedChanged);
4

1 に答える 1

1

ソリューション トリガーを必要とせずに目標を達成できると思います(このソリューションを小さなサンプルアプリでテストしました):したがって、スタイルは次のようになります。

<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
    <Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
  ...

ビュー モデルには 1 つのコマンドしかありません。そして、そのコマンドが選択されたアイテムのリストを受け取るパラメータとして。したがって、ユーザーがチェックボックスをオンにするかオフにするかという 1 つのことだけが欠けています。現時点では、この情報を SelectedItems と一緒に渡す 1 つの方法を考えることができます - SelectedItems と IsChecked の現在の値を Tuple<..., bool> のようなものに入れるカスタム コンバーターを使用して MultiBinding を記述します。

        <Setter Property="CommandParameter">
            <Setter.Value>
                <MultiBinding Converter="{x:Static PackTupleConverter.Instance}">
                    <Binding RelativeSource="{RelativeSource AncestorType=DataGrid}" Path="SelectedItems"/>
                    <Binding RelativeSource="{x:Static RelativeSource.Self}" Path="IsChecked"/>
                </MultiBinding>
            </Setter.Value>
        </Setter>

終わり

ListBox 内に同じチェックボックスを配置するだけで、問題を再現できました。初めてチェックボックスをクリックすると、コマンドが呼び出されません

サンプル ウィンドウ xaml は次のとおりです。

<Window.Resources>
    <Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Style.Triggers>
            <Trigger Property="IsChecked" Value="True">
                <Setter Property="Command" Value="{Binding DataContext.Test, RelativeSource={RelativeSource AncestorType=Window}}" />
            </Trigger>
            <Trigger Property="IsChecked" Value="False">
                <Setter Property="Command" Value="{Binding DataContext.Test, RelativeSource={RelativeSource AncestorType=Window}}" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <ListBox>
        <ListBox.Items>
            <CheckBox Style="{StaticResource CheckBoxSelectTypeStyle}" />
        </ListBox.Items>
    </ListBox>

</Grid>

そして後ろに乗ります:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Test = new DelegateCommand(TestCommand);
    }

    public ICommand Test { get; set; }

    private void TestCommand()
    {
    }
}

バインディングに関する出力で発見したことは次のとおりです。

System.Windows.Data 情報: 10 : バインディングを使用して値を取得できず、有効なフォールバック値が存在しません。代わりにデフォルトを使用します。BindingExpression:Path=DataContext.Test; DataItem=null; ターゲット要素は 'CheckBox' (Name='') です。ターゲット プロパティは 'Command' (タイプ 'ICommand') です。

于 2013-02-20T20:00:24.133 に答える