1

I have a textbox named "txtSearch"

I also have a DataGrid which is filled programmatically.

Now I want to search txtSearch.text in DataGridView and based on that I want to select the full row.

I want it to be done programmatically. I mean without using XAML.

Is it possible?

Vishal
  • 6,238
  • 10
  • 82
  • 158
  • 1
    why do you implement in WPF if you don't want to use XAML ? Use windows forms, instead. – Tigran May 27 '13 at 14:18
  • I have created an application in winforms. For easy and good animation I am translating my project to WPF. – Vishal May 27 '13 at 14:20
  • 2
    if you translating to WPF, it's better that you spend a time to learn databinding, cause it will bring to you *huge* benefits in WPF world. – Tigran May 27 '13 at 14:41
  • 100% agreed with @tigran, WPF is not about "good animation". It's about being able to actually develop something useful. Post the relevant code and XAML, and probably a screenshot of what you need. – Federico Berasategui May 27 '13 at 14:45

2 Answers2

1

First of all, if you're doing something in WPF you'd better do it the WPF Way.

If you're not interested in learning XAML and MVVM, then you'd rather go back to dinosaur useless technologies.

<Window x:Class="MiscSamples.DataGridSearch"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataGridSearch" Height="300" Width="300">
    <DockPanel>
        <DockPanel DockPanel.Dock="Top">
            <TextBlock Text="Search:" DockPanel.Dock="Left"/>
            <TextBox Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}"/>
        </DockPanel>

        <DataGrid ItemsSource="{Binding ItemsView}" AutoGenerateColumns="True"/>
    </DockPanel>
</Window>

Code Behind:

public partial class DataGridSearch : Window
{
    public DataGridSearch()
    {
        InitializeComponent();

        DataContext = new DataGridSearchViewModel();
    }
}

ViewModel:

public class DataGridSearchViewModel: PropertyChangedBase
{
    private string _searchString;
    public string SearchString
    {
        get { return _searchString; }
        set
        {
            _searchString = value;
            OnPropertyChanged("SearchString");
            ItemsView.Refresh();
        }
    }

    private ICollectionView _itemsView;
    public ICollectionView ItemsView
    {
        get { return _itemsView; }
    }

    private ObservableCollection<DataGridSearchModel> _items;
    public ObservableCollection<DataGridSearchModel> Items
    {
        get { return _items ?? (_items = new ObservableCollection<DataGridSearchModel>()); }
    }

    public DataGridSearchViewModel()
    {
        _itemsView = CollectionViewSource.GetDefaultView(Items);
        _itemsView.Filter = x => Filter(x as DataGridSearchModel);

        Enumerable.Range(0, 100)
                  .Select(x => CreateRandomItem())
                  .ToList()
                  .ForEach(Items.Add);
    }

    private bool Filter(DataGridSearchModel model)
    {
        var searchstring = (SearchString ?? string.Empty).ToLower();

        return model != null &&
             ((model.LastName ?? string.Empty).ToLower().Contains(searchstring) ||
              (model.FirstName ?? string.Empty).ToLower().Contains(searchstring) ||
              (model.Address ?? string.Empty).ToLower().Contains(searchstring));
    }

    private DataGridSearchModel CreateRandomItem()
    {
        return new DataGridSearchModel
                   {
                       LastName = RandomGenerator.GetNext(1),
                       FirstName = RandomGenerator.GetNext(1),
                       Address = RandomGenerator.GetNext(4)
                   };
    }
}

Data Item:

public class DataGridSearchModel:PropertyChangedBase
{
    public string LastName { get; set; }

    public string FirstName { get; set; }

    public string Address { get; set; }
}

PropertyChangedBase (MVVM helper class):

public class PropertyChangedBase:INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        Application.Current.Dispatcher.BeginInvoke((Action) (() =>
                                                                 {
                                                                     PropertyChangedEventHandler handler = PropertyChanged;
                                                                     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
                                                                 }));
    }
}

Random Generator (just to generate random strings)

public static class RandomGenerator
{
    private static string TestData = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum";
    private static List<string> words;
    private static int maxword;
    private static Random random = new Random();

    static RandomGenerator()
    {
        words = TestData.Split(' ').ToList();
        maxword = words.Count - 1;
    }

    public static string GetNext(int wordcount)
    {
        return string.Join(" ", Enumerable.Range(0, wordcount)
                                          .Select(x => words[random.Next(0, maxword)]));
    }

    public static int GetNextInt(int min, int max)
    {
        return random.Next(min, max);
    }
}

Result:

enter image description here

  • Fully MVVM.
  • There's not a single line of code that manipulates any UI element. This is the WPF way.
  • UpdateSourceTrigger=PropertyChanged in the TextBox binding makes it search as you type.
  • Fully strongly typed object model much better than using DataTables and stuff like that.
  • WPF rocks. Just copy and paste my code in a File -> New Project -> WPF Application and see the results for yourself.
  • Forget the winforms mentality, it's irrelevant, clumsy, generates bad code and just feels noob and immature.
Community
  • 1
  • 1
Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
  • Thanks for the answer. I am a VB guy. So I will first convert your code and try to implement it. After trying I will be here. – Vishal May 27 '13 at 15:48
  • @Vishal There is a [Visual Studio Extension](http://visualstudiogallery.msdn.microsoft.com/94c245e9-547a-4e47-87da-08dbcd283d7f) you can install that performs conversion between VB.Net and C#, if you like. – Federico Berasategui May 27 '13 at 15:52
  • I get an error here (_items = new ObservableCollection()); The error is Operator = is not defined for System.Collections.ObjectModel.ObsevableCollection(Of MyProject.DataGridSearchModal) and System.Collections.ObjectModel.ObsevableCollection(Of MyProject.DataGridSearchModal) – Vishal May 27 '13 at 16:30
  • @Vishal In VB.Net it should be `(_items = new ObservableCollection(of DataGridSearchModel))` – Federico Berasategui May 27 '13 at 16:32
  • @Vishal You need to change the C# `??` operator for `If()` in VB.Net. Look at [this](http://stackoverflow.com/a/403460/643085) – Federico Berasategui May 27 '13 at 16:36
  • @Vishal Then i'm not sure where the error is. Maybe post the new code? – Federico Berasategui May 27 '13 at 16:38
  • if you have time then please post. – Vishal May 27 '13 at 16:40
  • searching on google I found a post with similar problem http://stackoverflow.com/questions/15467553/proper-datagrid-search-from-textbox-in-wpf-using-mvvm – Vishal May 27 '13 at 16:54
0

you may want to use databinding like the ff. code below

Dim m_Dt As New DataTable
Dim m_Bs As New BindingSource

Private Sub createDatatable()
    m_Dt.Columns.Clear()
    m_Dt.Columns.Add("FieldKey", GetType(System.Int16))
    m_Dt.Columns.Add("Field1", GetType(System.String))
    m_Dt.Columns.Add("Field2", GetType(System.String))
End Sub

Private Sub PopulateDatatable()
    For i As Integer = 0 To 10
        Dim dr As DataRow = m_Dt.NewRow
        dr("FieldKey") = i
        dr("Field1") = String.Format("field1Value-{0}", i)
        dr("field2") = String.Format("Field2Value-{0}", i)
        dr = m_Dt.Rows.Add
    Next

End Sub

Private Sub BindDatatableToDataGridView()
    m_Bs.DataSource = m_Dt
    m_DataGridview.DataSource = m_Bs
End Sub

Private Sub FindTextAndFocusOnRow()
    m_Bs.Position = m_Bs.Find("FieldKey", m_TxtSearchText.Text)
End Sub


Private Sub ModifyRowValues()
    m_Dt.Rows(m_Bs.Position)("Field1") = "FieldModified"
End Sub
Winston Madiano
  • 87
  • 2
  • 11