0

Сразу скажу что я только учусь (самообучение), так вот у меня есть DataGrid в котором есть кнопка и 2 textbox-а, я получил доступ к кнопке и первому textbox-у, не могу понять как получать доступ к 2-му texbox?

xaml:

 <Grid Margin="10">
    <StackPanel Margin="5">
        <Grid Margin="10" HorizontalAlignment="Center">
            <Button Name="buttonAddGame"  Width="100"  HorizontalAlignment="Left" Content="Добавить Игру" Click="buttonAddGame_Click"/>
            <TextBox Name="textAddGame" Width="100"  materialDesign:HintAssist.Hint="новая игра" HorizontalAlignment="Left" Margin=" 130 0 0 0"/>
            <Button Name="update" Width="100" HorizontalAlignment="Right" Content="Обновить" Click="update_Click" Margin="350 0 0 0" Cursor="Hand" />
        </Grid>
        <DataGrid x:Name="lbMain" Margin="10" Width="auto" AutoGenerateColumns="False" VerticalAlignment="Top" HorizontalAlignment="Center" IsReadOnly="True" >
            <DataGrid.Columns>
                <DataGridTextColumn Header="Игра" Binding="{Binding Path='Name'}" IsReadOnly="True" />
                <DataGridTextColumn Header="Донат" Binding="{Binding Path='Donate'}" IsReadOnly="True" />
                <DataGridTextColumn Header="Голос" Binding="{Binding Path='Poll'}" IsReadOnly="True" />
                <DataGridTextColumn Header="Время Стрима" Binding="{Binding Path='StreamTime'}" IsReadOnly="True" />
            &lt;DataGridTemplateColumn Header=&quot;&quot; &gt;
                &lt;DataGridTemplateColumn.CellTemplate&gt;
                    &lt;DataTemplate&gt;
                        &lt;Button  Name=&quot;btnChange&quot; Content=&quot;Изменить&quot; Click=&quot;btnChange_Click&quot; /&gt;
                    &lt;/DataTemplate&gt;
                &lt;/DataGridTemplateColumn.CellTemplate&gt;
            &lt;/DataGridTemplateColumn&gt;

            &lt;DataGridTemplateColumn Header=&quot;+ Донат&quot; &gt;
                &lt;DataGridTemplateColumn.CellTemplate&gt;
                    &lt;DataTemplate&gt;
                        &lt;TextBox x:Name=&quot;textUpdateDonate&quot;  Width=&quot;100&quot; Text=&quot;&quot;  /&gt;
                    &lt;/DataTemplate&gt;
                &lt;/DataGridTemplateColumn.CellTemplate&gt;
            &lt;/DataGridTemplateColumn&gt;

            &lt;DataGridTemplateColumn Header=&quot;+ Голос&quot; &gt;
                &lt;DataGridTemplateColumn.CellTemplate&gt;
                    &lt;DataTemplate&gt;
                        &lt;TextBox x:Name=&quot;textUpdatePoll&quot;  Width=&quot;100&quot; Text=&quot;&quot; /&gt;
                    &lt;/DataTemplate&gt;
                &lt;/DataGridTemplateColumn.CellTemplate&gt;
            &lt;/DataGridTemplateColumn&gt;
        &lt;/DataGrid.Columns&gt;
    &lt;/DataGrid&gt;
    &lt;Button Margin=&quot;0 50 0 0&quot; x:Name=&quot;close&quot; Content=&quot;Выйти&quot; Width=&quot;100&quot; HorizontalAlignment=&quot;Center&quot; Click=&quot;close_Click&quot; Background=&quot;#FFFDFDFD&quot; BorderBrush=&quot;White&quot; Foreground=&quot;#DD6F6F6F&quot; Cursor=&quot;Hand&quot;/&gt;
&lt;/StackPanel&gt;

</Grid>

C#:

private void btnChange_Click(object sender, RoutedEventArgs e)
    {
    //var dataRow = (Game)((Button)e.Source).DataContext;
    object ordinal = e.OriginalSource;
    DataGrid dataGrid = FindParent&lt;DataGrid&gt;((DependencyObject)ordinal);
    TextBox tb = FindVisualChild&lt;TextBox&gt;(dataGrid);

    MessageBox.Show(tb.Text);
}

private void close_Click(object sender, RoutedEventArgs e)
{
    Environment.Exit(0);
}

private void update_Click(object sender, RoutedEventArgs e)
{
    lbMain.Items.Refresh();
}

public static parentItem FindParent&lt;parentItem&gt;(DependencyObject obj)
    where parentItem : DependencyObject
{
    DependencyObject objToRet = obj;
    while (!(objToRet is parentItem))
    {
        objToRet = VisualTreeHelper.GetParent(objToRet);
        if (objToRet == null) return null;
    }
    return (parentItem)objToRet;
}

public static childItem FindVisualChild&lt;childItem&gt;(DependencyObject obj)
    where childItem : DependencyObject
{
    for (int i = 0; i &lt; VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child != null &amp;&amp; child is childItem)
            return (childItem)child;
        else
        {
            childItem childOfChild = FindVisualChild&lt;childItem&gt;(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}

}

Класс Game:

public string Name
    {
        get { return name; }
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }
    public double Donate
    {
        get { return donate; }
        set
        {
            donate = value;
            OnPropertyChanged("Donate");
        }
    }
    public int Poll
    {
        get { return poll; }
        set
        {
            poll = value;
            OnPropertyChanged("Poll");
        }
    }
public double StreamTime
{
    get { return streamTime; }
    set
    {
        streamTime = value;
        OnPropertyChanged(&quot;StreamTime&quot;);
    }

}
public string TextBoxDonate
{
    get { return textBoxDonate; }
    set
    {
        textBoxDonate = value;
        OnPropertyChanged(&quot;TextBoxDonate&quot;);
    }
}

public string TextBoxPoll
{
    get { return textBoxPoll; }
    set
    {
        textBoxPoll = value;
        OnPropertyChanged(&quot;TextBoxPoll&quot;);
    }
}


public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = &quot;&quot;)
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(prop));
}

вот так выглядит приложение

собственно по нажатию на кнопку я хочу получить доступ к тексту который введен в обоих textbox-ах, я так понял нужно что то переписать, но голова уже не соображает

Damir
  • 3
  • Весь ваш код замените на DataContext = класс;, где класс это простой класс с нужными публичными свойствами для привязки, далее в XAML все x:Name заменяете на привязки к нужным свойствам, например x:Name="lbMain" меняете на ItemsSource = "{Binding Items}" (Items - свойство коллекции в классе), все, у вас несколько строк кода, вы не делаете костыли по типу поиска элемента, не храните данные в UI, у вас все на своих местах и все как надо. Имея это уже дальше можете работать, например Click заменить на Command, тогда передача данных будет просто CommandParameter = "{Binding}". – EvgeniyZ Nov 20 '22 at 11:16
  • проблема в том что, я только учусь и понимаю только на рабочих примерах, когда искал решение нашел такую реализацию как у меня в коде, да костыль на работает =) Если не затруднит можно больше кода для примера ? – Damir Nov 20 '22 at 11:25
  • я только учусь - по этой причине я и говорю вам, что вы делаете все не так, научитесь сразу использовать WPF правильно. больше кода для примера - куда еще больше?) Я вам считай пошаговую инструкцию дал, можете посмотреть также мои ответы по WPF, там найдете кучу полезного. Зовется это все "Привязки". Вы начните делать, а если возникнут вопросы, пишите, помогу. – EvgeniyZ Nov 20 '22 at 11:31
  • у меня проблема сразу на первом шаге =) DataContext = класс.. у меня уже есть класс Game (добавил его в вопрос сверху), при попытке сделать DataContext = Game; висит ошибка : Game является тип, который недопустим в данном контексте. – Damir Nov 20 '22 at 11:37
  • Наверно потому, что new Game();? Как в C# инициализируются классы? Ну и DataContext должен задаваться классу окна (про это я забыл сказать). – EvgeniyZ Nov 20 '22 at 11:40
  • CommandParameter = "{Binding}" можно подробней ? это в кнопке мы меняем click на CommandParameter = "{Binding}" правильно? а что в биндинг прописываем ? или это уже готовый код ? – Damir Nov 20 '22 at 12:05
  • Смотрите, Click - это событие, стандартное, простое событие, его аналогом в привязках являются команды, где вы в классе делаете публичное свойство (помним, что привязки доступны только к ним) с типом ICommand, далее вам нужно реализовать эту команду любым удобным для вас способов, например можно взять от сюда класс RelayCommand, дальше вам надо создать эту команду, указав какой метод будет использоваться. В XAML вы привязываете команду (Command = "{Binding MyCommand}"), ну и передаете параметры через CommandParameter. – EvgeniyZ Nov 20 '22 at 12:13
  • {Binding} - если не указано чего либо, то это означает "Текущий объект целиком", в вашем случае это будет Game, значит и в команде получайте тип Game. Если нужно конкретное значение, то указывайте его, например {Binding Name}, будет вам имя, в обработчике команды тип тогда string. – EvgeniyZ Nov 20 '22 at 12:15

1 Answers1

0

во-первых, в xaml коде, там, где нужные textbox, нужно было дописать:

<TextBox Width="100" Text="{Binding Path=TextBoxDonate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  />

после чего написанное в данном текст боксе уже отображалось в поле TextBoxDonate, а именно:

 var ordinal = e.OriginalSource;
    if (ordinal is Button)
    {
        DataGridRow dataGrid = FindParent&lt;DataGridRow&gt;((DependencyObject)ordinal);

        if (dataGrid != null)
        {
            int idx = lbMain.ItemContainerGenerator.IndexFromContainer(dataGrid);
            var thisGame = Gamess[idx];

            //thisGame.TextBoxDonate и есть наш textbox
        }
    }

Damir
  • 3