Mamurbek
Mamurbek

Reputation: 79

Find Textbox in DataGrid WPF

I edited last question. I have 2 classes

    public class Signal: INotifyPropertyChanged 
{
    public string Name { get; set;}
    public Int32 Value { get; set;}

    private ObservableCollection < RawVal > rawValue1;
    public ObservableCollection < RawVal > rawValue 
    {
        get  { return rawValue1; }
        set 
        {   rawValue1 = value;
            OnPropertyChanged("rawValue");
            if (value != null && value.Count > 0) 
            {
             SelectedRaValue = value.First();
            }
        }
    }

    private RawVal selectedRaValue;
    public RawVal SelectedRaValue 
    {
        get 
        {
            return selectedRaValue;
        }
        set 
        {
            selectedRaValue = value;
            OnPropertyChanged("SelectedRaValue");
            ComboValue = value.name;
            OnPropertyChanged("ComboValue");
        }
    }    
    public string ComboValue 
    {
        get;
        set;
    }    
    #region Implementation of INotifyPropertyChanged    
    public event PropertyChangedEventHandler PropertyChanged;    
    protected virtual void OnPropertyChanged(string propertyName) 
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }    
    #endregion

}

And Here XAML:

 <DataGrid ItemsSource="{Binding}" Name="grdSignal" Grid.Row="1" CanUserAddRows="False" AutoGenerateColumns="False" SelectionChanged="grdSignal_SelectionChanged_1">
 <DataGrid.Columns>
    <DataGridTextColumn Header="Signal Name" Binding="{Binding Name}" Width="150"/>
                                <DataGridTemplateColumn Header="Physical Value" Width="120">
          <DataGridTemplateColumn.CellTemplate>
             <DataTemplate>
                  <ComboBox ItemsSource="{Binding rawValue, Mode=TwoWay}" SelectedItem="{Binding SelectedRaValue,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  DisplayMemberPath="name" Name="cmbVal"  
                       IsEditable="True" KeyDown="cmbVal_KeyDown"  />
             </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Value" Width="100">
            <DataGridTemplateColumn.CellTemplate>
               <DataTemplate>
                <TextBox Text="{Binding ComboValue}" Name="tBoxValue" TextChanged="tBoxVale_textChanged"/>
               </DataTemplate>
           </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
      <DataGridTemplateColumn Header="Comment" Width="200">
    <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
            <TextBox Text="{Binding Comment}"/>
             </DataTemplate>
     </DataGridTemplateColumn.CellTemplate>
   </DataGridTemplateColumn>
  </DataGrid.Columns>
 </DataGrid>      

enter image description here As shown in pic, when Combobox selected Item changes, Textbox value is changed according to SelectedItem of Combobox Now, here comes my problem. Combobox is Editable, if user enters anything (string), and presses ENTER Key, Combobox text goes to Textbox Text.

private void cmbVal_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Return)
        {               
            string s = ((ComboBox)sender).Text;
            DataGridRow row = sigGrid.ItemContainerGenerator.ContainerFromIndex(sigGrid.SelectedIndex) as DataGridRow;
            var i = 3;
            TextBox ele = sigGrid.FindName("tbValue") as TextBox;
        }

    }

And Result is: enter image description here

Upvotes: 1

Views: 3916

Answers (2)

Martin
Martin

Reputation: 5623

If you use bindings in your xaml, you obviously have a object used as a datacontext for your grid named grdSignal.

And from this line...

  <TextBox Text="{Binding Comment}"/>

I can see that the bound objects have a Comment property:

If you want to read or write this value, you have to locate the respective property is your data source which is bound to the grid (used a data context) and read or assign this property.

In your case, if your assign a value to this property (if it implements INotifyPropertyChanged) the TextBox will update automatically to the new value.

In summary:

  • If you use bindings, you have to read and assign from / to properties of your data classes in order to communicate with the UI. Bindings connect targets (controls in your UI) to sources (data in your data context class or view model), so there should be no need to name controls in your view.

  • If you do not use bindings, you can communicate with the UI using the code behind file and accessing elements by their names, but this is not the way it should be done in WPF (not MVVM style)

Upvotes: 1

Emmanuel DURIN
Emmanuel DURIN

Reputation: 4913

@Mamurbek,

You could use the FindVisualDescendants function of that post :
Datagrid templatecolumn update source trigger explicit only updates first row

Using that function, you could have all textboxes for instance :

var textboxes = AccessGrid.FindAllVisualDescendants()
    .Where(elt => elt.Name == "tBoxValue" )
    .OfType<TextBox>();

Only the first for instance :

var textboxes = AccessGrid.FindAllVisualDescendants()
    .Where(elt => elt.Name == "tBoxValue" )
    .OfType<TextBox>()
    .FirstOrDefault();

Or only the 3rd using Skip and Take :

int n = 3;
var textboxes = AccessGrid.FindAllVisualDescendants()
    .Where(elt => elt.Name == "tBoxValue" )
    .OfType<TextBox>()
    .Skip(n-1)
    .Take(1);

Hope it helps

Upvotes: 2

Related Questions