Can I do Text search with multibinding
Asked Answered
S

2

2

I have below combo box in mvvm-wpf application. I need to implement "Text search" in this..(along with multibinding). Can anybody help me please.

<StackPanel Orientation="Horizontal">
    <TextBlock Text="Bid Service Cat ID"
                Margin="2"></TextBlock>
    <ComboBox Width="200"
                Height="20"
                SelectedValuePath="BidServiceCategoryId"
                SelectedValue="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}},
                    Path=DataContext.SelectedBidServiceCategoryId.Value}"
                ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}},
                    Path=DataContext.BenefitCategoryList}"
                Margin="12,0">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock DataContext="{Binding}">
                            <TextBlock.Text>
                                <MultiBinding StringFormat="{}{0}: {1}">
                                <Binding Path="BidServiceCategoryId" />
                                <Binding Path="BidServiceCategoryName" />
                            </MultiBinding>
                            </TextBlock.Text></TextBlock>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</StackPanel>
Sprang answered 20/1, 2011 at 17:6 Comment(0)
C
6

Unfortunately, TextSearch.Text doesn't work in a DataTemplate. Otherwise you could have done something like this

<ComboBox ...>
    <ComboBox.ItemContainerStyle>
        <Style TargetType="{x:Type ComboBoxItem}">
            <Setter Property="TextSearch.Text">
                <Setter.Value>
                    <MultiBinding StringFormat="{}{0}: {1}">
                        <Binding Path="BidServiceCategoryId"/>
                        <Binding Path="BidServiceCategoryName"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

However this won't work, so I see two solutions to your problem.

First way
You set IsTextSearchEnabled to True for the ComboBox, override ToString in your source class and change the MultiBinding in the TextBlock to a Binding

Xaml

<ComboBox ...
          IsTextSearchEnabled="True">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>

Source class

public class TheNameOfYourSourceClass
{
    public override string ToString()
    {
        return String.Format("{0}: {1}", BidServiceCategoryId, BidServiceCategoryName);
    }
    //...
}

Second Way
If you don't want to override ToString I think you'll have to introduce a new Property in your source class where you combine BidServiceCategoryId and BidServiceCategoryName for the TextSearch.TextPath. In this example I call it BidServiceCategory. For this to work, you'll have to call OnPropertyChanged("BidServiceCategory"); when BidServiceCategoryId or BidServiceCategoryName changes as well. If they are normal CLR properties, you can do this in set, and if they are dependency properties you'll have to use the property changed callback

Xaml

<ComboBox ...
          TextSearch.TextPath="BidServiceCategory"
          IsTextSearchEnabled="True">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock DataContext="{Binding}">
                <TextBlock.Text>
                    <MultiBinding StringFormat="{}{0}: {1}">
                        <Binding Path="BidServiceCategoryId" />
                        <Binding Path="BidServiceCategoryName" />
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </ComboBox.ItemTemplate>

Source class

public class TheNameOfYourSourceClass
{
    public string BidServiceCategory
    {
        get
        {
            return String.Format("{0}: {1}", BidServiceCategoryId, BidServiceCategoryName);
        }
    }

    private string m_bidServiceCategoryId;
    public string BidServiceCategoryId
    {
        get
        {
            return m_bidServiceCategoryId;
        }
        set
        {
            m_bidServiceCategoryId = value;
            OnPropertyChanged("BidServiceCategoryId");
            OnPropertyChanged("BidServiceCategory");
        }
    }

    private string m_bidServiceCategoryName;
    public string BidServiceCategoryName
    {
        get
        {
            return m_bidServiceCategoryName;
        }
        set
        {
            m_bidServiceCategoryName = value;
            OnPropertyChanged("BidServiceCategoryName");
            OnPropertyChanged("BidServiceCategory");
        }
    }
}
Collincolline answered 20/1, 2011 at 18:46 Comment(8)
The first method ..is not working for me...it's not displaying. Only object is geting displayed..not value in thatSprang
@Anish Mohan: Have you checked if the ToString method is getting hit in the debugger? If so, what value does it return? Do you think it would help if I uploaded my sample project?Collincolline
Hi, ToString is not getting called .Sprang
The DataContext is BenefitCategoryList, which seems to be a Collection of something like BenefitCategory instances, is this correct? In that case, an instance of BenefitCategory should be the DataContext for each ComboBoxItem, and the ToString should be called to present each item. I'm not sure what's missing here. Can you post the source for the source class perhaps?Collincolline
YEs ...but BenefitCategory is a dto...and i have added ToString method over there. But it never called. I think..we have to have these two properties in viewmodel...and ToSting shud be in view modelSprang
When you bind directly to the DataContext, which is a class in this case, the framework will call the ToString method when presenting it. If you don't override ToString it will return the default value which is the fully qualified name, meaning namespace.classname. Hopefully that was clear, did it answer your question? :)Collincolline
Yes, very much..Thank youuuuuuuuuuuuuuuSprang
Does Solution 2 work when search anywhere in your string. For instance, does the search text need to start with BidServiceCategoryID since that is the first field displayed in BidServiceCategory? Basically can you do a wildcard or substring search with this solution?Ladonna
B
3

I don't know if your text search has to search ALL the text, but if you want to search from the category ID, you can just set the TextSearch.TextPath property to BidServiceCategoryId. That should also be helpful for anyone who wants to use multibinding and finds that the text search no longer works... It does work if you explicitly set the TextPath property.

Bromidic answered 2/8, 2011 at 15:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.