10

ComboBoxをエンティティにバインドしていますが、データをフィルタリングしたいと思います。

これまで、私は2つの方法を試しました。

  • 「単純な」もの:LINQtoEntitiesを介してObjectSetに直接フィルターを適用します
  • msdnで説明されているようにフィルタリングイベントハンドラーを設定する

データベースに対して生成されたクエリにWHERE句が含まれているため、最初のアプローチに満足しています。したがって、すべてのデータをリモートデータベースから取得する必要はありません。

ただし、実行時に適用されるフィルタリングを変更したい場合は、#2のアプローチの方がはるかに柔軟です... msdnの例に従いましたが、例外が発生します。なぜですか?

したがって、私の質問は次のとおり
です。1.どちらのアプローチが優れている
か2.なぜ例外が発生するのですか?

これが私のコードです:

 private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        //Do not load your data at design time.
        if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
        {
            //Load your data here and assign the result to the CollectionViewSource.
            System.Windows.Data.CollectionViewSource myCollectionViewSource =
                (System.Windows.Data.CollectionViewSource)
                this.Resources["tSCHEDEViewSource"];

            // If I use this I get the data filtered on startup, but is it the right mode?
            //myCollectionViewSource.Source = _context.TSCHEDE.Where(s => s.KLINEA == kLinea && s.FCANC == "T").OrderBy(s => s.DSCHEDA).OrderByDescending(s => s.DSTORICO);

            // Instead If I apply my custom filtering logic
            myCollectionViewSource.Filter += new FilterEventHandler(filterSource);

            myCollectionViewSource.Source = _context.TSCHEDE; // ... Here i get an exception: 
            // 'System.Windows.Data.BindingListCollectionView' view does not support filtering. ???
        }
    }


    private void filterSource(object sender, FilterEventArgs e)
    {
        TSCHEDE scheda = e.Item as TSCHEDE;
        if (scheda != null)
        {
            if (scheda.KLINEA == 990)
            {
                e.Accepted = true;
            }
            else
            {
                e.Accepted = false;
            }
        }
    }

編集:EventHandlerを設定するのではなく、ビューにFilterプロパティを実装しようとしました:

myCollectionView = (BindingListCollectionView)myCollectionViewSource.View;
myCollectionView.Filter = new Predicate<object>(Contains);

public bool Contains(object de)
    {
        TSCHEDE scheda = de as TSCHEDE;
        return (scheda.KLINEA == 990);
    }

そして今、私はそれほど有用ではない例外を受け取ります:

System.NotSupportedException:指定されたメソッドはサポートされていません。System.Windows.Data.CollectionView.set_Filter(Predicate`1 value)で

編集

XAMLコード:

<UserControl.Resources>
    <CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE, CreateList=True}"  >
    </CollectionViewSource>
    <DataTemplate x:Key="SchedaTemplate">
        <StackPanel Orientation="Horizontal" >
            <TextBlock Text="{Binding Path=KSCHEDA}" Width="60"></TextBlock>
            <TextBlock Text="{Binding Path=DArticolo}" Width="200"></TextBlock>
            <TextBlock Text=" - " Width="40"></TextBlock>
            <TextBlock Text="{Binding Path=DSTORICO}" Width="150"></TextBlock>
        </StackPanel>
    </DataTemplate>
</UserControl.Resources>
<Grid Background="PapayaWhip" DataContext="{StaticResource tSCHEDEViewSource}" DataContextChanged="StartHere" Name="rootGrid">
    <ComboBox ItemTemplate="{StaticResource SchedaTemplate}" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="23,129,0,0" Name="tSCHEDEComboBox1" SelectedValuePath="KSCHEDA" VerticalAlignment="Top" Width="393">
        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>
    </ComboBox>
</Grid>

今、私は問題がコードビハインドではなく、XAMLバインディングにあると考えています...

4

3 に答える 3

9

これをチェックして

1)CollectionViewフィルタリング

フィルタリングには、フィルターが発生するデリゲート(述語)が必要です。述語は、返す値trueまたはfalseに基づいてアイテムを取り込み、要素を選択または選択解除します。

this.Source.Filter = item => {
    ViewItem vitem = item as ViewItem;
    return vItem != null && vitem.Name.Contains("A");
};

2)データを動的にフィルタリングする

于 2013-01-24T09:38:46.450 に答える
7

最後に 、コレクションのタイプを明示的に宣言するためにこの質問にも投稿されているように、解決策を見つけました。

CollectionViewType = "ListCollectionView"

そのため、XAMLでコレクションタイプを追加しました。

<CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE,  CreateList=True}" CollectionViewType="ListCollectionView">
    </CollectionViewSource>

そして、コードでは、イベントハンドラーが機能するようになりました。

myCollectionViewSource.Filter += new FilterEventHandler(filterSource);

唯一の後悔は、なぜ非常に単純なものであるために、XAMLで「手動で」強制する必要があるのか​​理解できなかったことです。 私にはこれはハックのように見え、また非常にエラーが発生しやすいです...

于 2013-01-24T11:29:40.930 に答える
0
<TextBox x:Name="FilterTextBox">
    <b:Interaction.Triggers>
        <b:EventTrigger EventName="TextChanged">
            <b:CallMethodAction
                MethodName="Refresh"
                TargetObject="{Binding View, BindsDirectlyToSource=True, Source={StaticResource tSCHEDEViewSource}}" />
        </b:EventTrigger>
    </b:Interaction.Triggers>
</TextBox>
于 2020-04-14T18:32:51.070 に答える