Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

huangapple go评论64阅读模式
英文:

Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

问题

我有一个DataGrid,我在其中使用CellTemplate来定义各种数据列。如下所示:

<DataGridTemplateColumn Header="电影来源" Width="*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox x:Name="cbMovieSource" Width="100" 
                      ItemsSource="{Binding Path=MovieSources, Mode=Twoway}" 
                      SelectedItem="{Binding Path=MovieSourceSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}" 
                      IsSynchronizedWithCurrentItem="False">
            </ComboBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

现在,在该DataGrid中我有3/4个数据列,基于一个名为'电影来源'的数据列 - ComboBox的值为"手动输入",我需要将另一个名为'电影厅'的数据列的ComboBox更改为TextBox,以允许用户输入数据。我已经使用了Data Trigger来实现这一点。

问题是 -

  1. 在加载页面时,最初显示的是空白,而不是默认的ComboBox - '电影厅'。

  2. 当我将电影来源ComboBox的值更改为"手动输入"时,电影厅ComboBox没有变成TextBox,但如果我在空白处单击,TextBox会出现。

我使用Observable Collection作为项源,数据加载没有问题。但是如何在最初获取ComboBox,然后在从ComboBox中选择特定值后将其更改为TextBox是这里的问题。

我的Data trigger代码如下:

<DataGridTemplateColumn Header="电影厅" Width="*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ContentControl>
                <ContentControl.Style>
                    <Style TargetType="av:ContentControl">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding ElementName=cbMovieSource, Path=SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <ComboBox x:Name="cbMovieHall" Width="120" 
                                                      ItemsSource="{Binding MovieHalls, Mode=Twoway}" 
                                                      SelectedItem="{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}">      
                                            </ComboBox>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=MovieSourceSelected}" Value="手动输入">
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBox Width="120"  Visibility="Visible" 
                                                     Text="{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=DataGridRow}}"/>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

初始加载:

Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

选择值后:

Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

单击电影厅标题下的空白处后:

Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

英文:

I have one DataGrid where I am using CellTemplate to define various Data columns.
Like below

&lt;DataGridTemplateColumn Header=&quot;Movie Source&quot; Width=&quot;*&quot;&gt;
      &lt;DataGridTemplateColumn.CellTemplate&gt;
           &lt;DataTemplate&gt;
              &lt;ComboBox x:Name=&quot;cbMovieSource&quot; Width=&quot;100&quot; 
                      ItemsSource=&quot;{Binding Path=MovieSources, Mode=Twoway}&quot; 
                      SelectedItem=&quot;{Binding Path=MovieSourceSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}&quot; 
                      IsSynchronizedWithCurrentItem=&quot;False&quot;&gt;
              &lt;/ComboBox&gt;
           &lt;/DataTemplate&gt;
       &lt;/DataGridTemplateColumn.CellTemplate&gt;
    &lt;/DataGridTemplateColumn&gt;

Now, I have 3/4 data columns in that DataGrid, Based on one Data column 'Movie Source'- ComboBox's value
" Manual Entry", I have to change another Data column 'Movie Hall' ComboBox into TextBox to allow user enter data. I have used Data trigger to do that.

Problem is --

  1. While loading page initially its showing blank instead of default ComboBox -'Movie Hall'.

  2. And while I am changing Movie Source ComboBox's value to
    "Manual Entry" its not changing Movie Hall ComboBox into TextBox but if I click in
    that blank space TextBox appearing.

I am using Observable Collection for Item source and data loading is not a problem.
But how I will get initially ComboBox but after selecting certain value from ComboBox, into TextBox is the issue here.

My Data trigger code is like below -

&lt;DataGridTemplateColumn Header=&quot;Movie Hall&quot; Width=&quot;*&quot;&gt;
    &lt;DataGridTemplateColumn.CellTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;ContentControl&gt;
                &lt;ContentControl.Style&gt;
                    &lt;Style TargetType=&quot;av:ContentControl&quot; &gt;
                        &lt;Style.Triggers&gt;
                            &lt;DataTrigger Binding=&quot;{Binding ElementName=cbMovieSource, Path=SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot;&gt;
                                &lt;Setter Property=&quot;ContentTemplate&quot;&gt;
                                    &lt;Setter.Value&gt;
                                        &lt;DataTemplate&gt;
                                            &lt;ComboBox x:Name=&quot;cbMovieHall&quot; Width=&quot;120&quot; 
                                                      ItemsSource=&quot;{Binding MovieHalls, Mode=Twoway}&quot; 
                                                      SelectedItem=&quot;{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}&quot;&gt;      
                                            &lt;/ComboBox&gt;
                                        &lt;/DataTemplate&gt;
                                    &lt;/Setter.Value&gt;
                                &lt;/Setter&gt;
                            &lt;/DataTrigger&gt;
                            &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected}&quot; Value =&quot;Manual Entry&quot;&gt;
                                &lt;Setter Property=&quot;ContentTemplate&quot;&gt;
                                    &lt;Setter.Value&gt;
                                        &lt;DataTemplate&gt;
                                            &lt;TextBox Width=&quot;120&quot;  Visibility=&quot;Visible&quot; 
                                                Text=&quot;{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=DataGridRow}}&quot;/&gt;
                                        &lt;/DataTemplate&gt;
                                    &lt;/Setter.Value&gt;
                                &lt;/Setter&gt;
                            &lt;/DataTrigger&gt;
                        &lt;/Style.Triggers&gt;
                    &lt;/Style&gt;
                &lt;/ContentControl.Style&gt;
            &lt;/ContentControl&gt;
       &lt;/DataTemplate&gt;
    &lt;/DataGridTemplateColumn.CellTemplate&gt;
&lt;/DataGridTemplateColumn&gt;

Initial Loading

Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

After selecting value
Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

After clicking on blank space under Movie Hall header-

Based on ComboBox selection, change another ComboBox to TextBox using DataTrigger inside DataGrid CellTemplate

答案1

得分: 2

I think now issue is not in any xaml code written here, everything is just fine with DataTrigger, CellTemplate etc. Because you mentioned after clicking its changing means trigger working but UpdateSourceTrigger = PropertyChanged not working that's why Trigger is firing after manual click.

You also mentioned all other columns and this column also working fine with Data population that means all your ComboBox columns are having item source with collection which is declared in mvvm style, INotifyPropertyChanged. And I see in comment that selected property is string and item source is collection of string.

You have not wrote any c# code for those properties but with the problem I am assuming you have observable collections with data class not direct string collection.
Please make sure your c# code is like below in ViewModel class -

 private ObservableCollection&lt;MovieData&gt; _dataGridCollection;
    public ObservableCollection&lt;MovieData&gt; DataGridCollection 
    {
          get =&gt; _dataGridCollection;
          set
          {
              var changed = DataGridCollection != value;
              if (changed)
              {
                  _dataGridCollection = value;
                  NotifyPropertyChanged($&quot;DataGridCollection &quot;);
               }
           }
    }

And Model class like below -

 Public class MovieData : INotifyPropertyChanged
    {
    	private string _movieSourceSelected;
        public string MovieSourceSelected
        {
            get =&gt; _movieSourceSelected;
            set
            {
               _movieSourceSelected = value;
               NotifyPropertyChanged(&quot;MovieSourceSelected&quot;);
             }
        }
    }

And for Xaml part, @Étienne Laneville wrote excellent code there, nothing is wrong in that part but still for answer completion adding to his answer with few minor modifications like Direct Visibility set in control itself and again inside style setter will prevent data trigger to work properly and Grid to StackPanel and Hidden to Collapsed as Hidden always occupies the space and StackPanel puts controls with VerticalOrientation default with one control after another not with same space, which is required here and Grid will put both control in same place..

&lt;DataGridTemplateColumn Header=&quot;Movie Hall&quot; Width=&quot;*&quot;&gt;
    &lt;av:DataGridTemplateColumn.CellTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;StackPanel&gt;
                &lt;ComboBox Width=&quot;120&quot;     
                          IsSynchronizedWithCurrentItem=&quot;False&quot;                                  
                          ItemsSource=&quot;{Binding MovieHalls, Mode=Twoway}&quot;
                          SelectedItem=&quot;{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}&quot;&gt;
                            &lt;ComboBox.Style&gt;
                                &lt;Style TargetType=&quot;ComboBox&quot;&gt;
                                    &lt;Setter Property=&quot;Visibility&quot; Value=&quot;Visible&quot; /&gt;
                                        &lt;Style.Triggers&gt;
                                            &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot; 
                                                         Value=&quot;Manual Entry&quot;&gt;
                                                &lt;Setter Property=&quot;Visibility&quot; Value=&quot;Collapsed&quot; /&gt;
                                            &lt;/DataTrigger&gt;
                                        &lt;/Style.Triggers&gt;
                                &lt;/Style&gt;
                            &lt;/ComboBox.Style&gt;
                &lt;/ComboBox&gt;
                 &lt;TextBox Width=&quot;120&quot;                                                   
                          Text=&quot;{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=av:DataGridRow}}&quot;&gt;
                            &lt;TextBox.Style&gt;
                                &lt;Style TargetType=&quot;TextBox&quot;&gt;
                                    &lt;Setter Property=&quot;Visibility&quot; Value=&quot;Collapsed&quot; /&gt;
                                        &lt;Style.Triggers&gt;
                                            &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot; 
                                                         Value=&quot;Manual Entry&quot;&gt;
                                                    &lt;Setter Property=&quot;Visibility&quot;  Value=&quot;Visible&quot; /&gt;
                                            &lt;/DataTrigger&gt;
                                        &lt;/Style.Triggers&gt;
                                &lt;/Style&gt;
                            &lt;/TextBox.Style&gt;
                &lt;/TextBox&gt;
             &lt;/StackPanel&gt;
        &lt;/DataTemplate&gt;
     &lt;/DataGridTemplateColumn.CellTemplate&gt;
&lt;/DataGridTemplateColumn&gt;

Edit after answer acceptance :Long story short, your ComboBox was not changing into TextBox because your trigger was not firing automatically. And your trigger was not firing automatically because your UpdateSourceTrigger = PropertyChanged was not working. And UpdateSourceTrigger was not working because your c# code was missing INotifyPropertyChanged implementation with that bind property of Selected Item of Source ComboBox.

英文:

I think now issue is not in any xaml code written here, everything is just fine with DataTrigger, CellTemplate etc. Because you mentioned after clicking its changing means trigger working but UpdateSourceTrigger = PropertyChanged not working that's why Trigger is firing after manual click.

You also mentioned all other columns and this column also working fine with Data population that means all your ComboBox columns are having item source with collection which is declared in mvvm style, INotifyPropertyChanged. And I see in comment that selected property is string and item source is collection of string.

You have not wrote any c# code for those properties but with the problem I am assuming you have observable collections with data class not direct string collection.
Please make sure your c# code is like below in ViewModel class -

 private ObservableCollection&lt;MovieData&gt; _dataGridCollection;
    public ObservableCollection&lt;MovieData&gt; DataGridCollection 
    {
          get =&gt; _dataGridCollection;
          set
          {
              var changed = DataGridCollection != value;
              if (changed)
              {
                  _dataGridCollection = value;
                  NotifyPropertyChanged($&quot;DataGridCollection &quot;);
               }
           }
    }

And Model class like below -

 Public class MovieData : INotifyPropertyChanged
    {
    	private string _movieSourceSelected;
        public string MovieSourceSelected
        {
            get =&gt; _movieSourceSelected;
            set
            {
               _movieSourceSelected = value;
               NotifyPropertyChanged(&quot;MovieSourceSelected&quot;);
             }
        }
    }

And for Xaml part, @Étienne Laneville wrote excellent code there, nothing is wrong in that part but still for answer completion adding to his answer with few minor modifications like Direct Visibility set in control itself and again inside style setter will prevent data trigger to work properly and Grid to StackPanel and Hidden to Collapsed as Hidden always occupies the space and StackPanel puts controls with VerticalOrientation default with one control after another not with same space, which is required here and Grid will put both control in same place..

&lt;DataGridTemplateColumn Header=&quot;Movie Hall&quot; Width=&quot;*&quot;&gt;
    &lt;av:DataGridTemplateColumn.CellTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;StackPanel&gt;
                &lt;ComboBox Width=&quot;120&quot;     
                          IsSynchronizedWithCurrentItem=&quot;False&quot;                                  
                          ItemsSource=&quot;{Binding MovieHalls, Mode=Twoway}&quot;
                          SelectedItem=&quot;{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}&quot;&gt;
                            &lt;ComboBox.Style&gt;
                                &lt;Style TargetType=&quot;ComboBox&quot;&gt;
                                    &lt;Setter Property=&quot;Visibility&quot; Value=&quot;Visible&quot; /&gt;
                                        &lt;Style.Triggers&gt;
                                            &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot; 
                                                         Value=&quot;Manual Entry&quot;&gt;
                                                &lt;Setter Property=&quot;Visibility&quot; Value=&quot;Collapsed&quot; /&gt;
                                            &lt;/DataTrigger&gt;
                                        &lt;/Style.Triggers&gt;
                                &lt;/Style&gt;
                            &lt;/ComboBox.Style&gt;
                &lt;/ComboBox&gt;
                 &lt;TextBox Width=&quot;120&quot;                                                   
                          Text=&quot;{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=av:DataGridRow}}&quot;&gt;
                            &lt;TextBox.Style&gt;
                                &lt;Style TargetType=&quot;TextBox&quot;&gt;
                                    &lt;Setter Property=&quot;Visibility&quot; Value=&quot;Collapsed&quot; /&gt;
                                        &lt;Style.Triggers&gt;
                                            &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}&quot; 
                                                         Value=&quot;Manual Entry&quot;&gt;
                                                    &lt;Setter Property=&quot;Visibility&quot;  Value=&quot;Visible&quot; /&gt;
                                            &lt;/DataTrigger&gt;
                                        &lt;/Style.Triggers&gt;
                                &lt;/Style&gt;
                            &lt;/TextBox.Style&gt;
                &lt;/TextBox&gt;
             &lt;/StackPanel&gt;
        &lt;/DataTemplate&gt;
     &lt;/DataGridTemplateColumn.CellTemplate&gt;
&lt;/DataGridTemplateColumn&gt;

Edit after answer acceptance :Long story short, your ComboBox was not changing into TextBox because your trigger was not firing automatically. And your trigger was not firing automatically because your UpdateSourceTrigger = PropertyChanged was not working. And UpdateSourceTrigger was not working because your c# code was missing INotifyPropertyChanged implementation with that bind property of Selected Item of Source ComboBox.

答案2

得分: 1

I think you only need one DataTrigger, the second one. Use the Setter from the first DataTrigger by itself in the Style (this will be the default), and then have the Style.Triggers section with just the second DataTrigger:

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <ContentControl>
            <ContentControl.Style>
                <Style TargetType="av:ContentControl">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <ComboBox x:Name="cbMovieHall"
                                            Width="120"
                                            ItemsSource="{Binding MovieHalls, Mode=Twoway}"
                                            SelectedItem="{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}">
                                </ComboBox>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=MovieSourceSelected}"
                                        Value="Manual Entry">
                            <Setter Property="ContentTemplate">
                                <Setter.Value>
                                    <DataTemplate>
                                        <TextBox Width="120"
                                                    Visibility="Visible"
                                                    Text="{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=DataGridRow}}" />
                                    </DataTemplate>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

The first Setter in the Style will be applied by default. Then, if the DataTrigger condition is met, the Setter in that DataTrigger will also be applied, overwriting the first Setter and, in this case, setting the ContentTemplate to the DataTemplate with a TextBox in it.

You can also simplify things by having the ComboBox and TextBox handle hiding themselves based on the DataTrigger instead of using a ContentControl:

<DataGridTemplateColumn Header="Movie Hall"
                        Width="*">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <ComboBox Width="120"
                          ItemsSource="{Binding MovieHalls, Mode=Twoway}"
                          SelectedItem="{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}">
                    <ComboBox.Style>
                        <Style TargetType="ComboBox">
                            <Setter Property="Visibility"
                                    Value="Visible" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=MovieSourceSelected}"
                                                Value="Manual Entry">
                                    <Setter Property="Visibility"
                                            Value="Hidden" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ComboBox.Style>
                </ComboBox>
                <TextBox Width="120"
                            Visibility="Visible"
                            Text="{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=DataGridRow}}">
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Setter Property="Visibility"
                                    Value="Hidden" />
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=MovieSourceSelected}"
                                                Value="Manual Entry">
                                    <Setter Property="Visibility"
                                            Value="Visible" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

This XAML has a ComboBox that is Visible by default and set to Hidden when MovieSourceSelected is Manual Entry. The TextBox is Hidden by default and set to Visible with Manual Entry.

Regarding the Binding used for your Movie Source ComboBox, make sure it uses SelectedValue and SelectedValuePath if you are using a String as your Dependency Property:

<ComboBox SelectedValue="{Binding MovieSourceSelected, Mode=TwoWay}" SelectedValuePath="Content">
    <ComboBoxItem Content="Some option" />
    <ComboBoxItem Content="Manual Insertion" />
    <ComboBoxItem Content="Some other option" />
</ComboBox>

As a side note, you should not have to name your ComboBoxes (cboMovieSource and cbMovieHall) since they are working with bindings. You'd name them if you needed to access them in code-behind, but from your XAML, it doesn't look like you need to.

英文:

I think you only need one DataTrigger, the second one. Use the Setter from the first DataTrigger by itself in the Style (this will be the default), and then have the Style.Triggers section with just the second DataTrigger:

&lt;DataGridTemplateColumn.CellTemplate&gt;
    &lt;DataTemplate&gt;
        &lt;ContentControl&gt;
            &lt;ContentControl.Style&gt;
                &lt;Style TargetType=&quot;av:ContentControl&quot;&gt;
                    &lt;Setter Property=&quot;ContentTemplate&quot;&gt;
                        &lt;Setter.Value&gt;
                            &lt;DataTemplate&gt;
                                &lt;ComboBox x:Name=&quot;cbMovieHall&quot;
                                            Width=&quot;120&quot;
                                            ItemsSource=&quot;{Binding MovieHalls, Mode=Twoway}&quot;
                                            SelectedItem=&quot;{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}&quot;&gt;
                                &lt;/ComboBox&gt;
                            &lt;/DataTemplate&gt;
                        &lt;/Setter.Value&gt;
                    &lt;/Setter&gt;
                    &lt;Style.Triggers&gt;
                        &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected}&quot;
                                        Value=&quot;Manual Entry&quot;&gt;
                            &lt;Setter Property=&quot;ContentTemplate&quot;&gt;
                                &lt;Setter.Value&gt;
                                    &lt;DataTemplate&gt;
                                        &lt;TextBox Width=&quot;120&quot;
                                                    Visibility=&quot;Visible&quot;
                                                    Text=&quot;{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=DataGridRow}}&quot; /&gt;
                                    &lt;/DataTemplate&gt;
                                &lt;/Setter.Value&gt;
                            &lt;/Setter&gt;
                        &lt;/DataTrigger&gt;
                    &lt;/Style.Triggers&gt;
                &lt;/Style&gt;
            &lt;/ContentControl.Style&gt;
        &lt;/ContentControl&gt;
    &lt;/DataTemplate&gt;
&lt;/DataGridTemplateColumn.CellTemplate&gt;

</DataGridTemplateColumn>

The first Setter in the Style will be applied by default. Then, if the DataTrigger condition is met, the Setter in that DataTrigger will also be applied, overwriting the first Setter and, in this case, setting the ContentTemplate to the DataTemplate with a TextBox in it.

You can also simplify things by having the ComboBox and TextBox handle hiding themselves based on the DataTrigger instead of using a ContentControl:

&lt;DataGridTemplateColumn Header=&quot;Movie Hall&quot;
                        Width=&quot;*&quot;&gt;
    &lt;DataGridTemplateColumn.CellTemplate&gt;
        &lt;DataTemplate&gt;
            &lt;Grid&gt;
                &lt;ComboBox Width=&quot;120&quot;
                          ItemsSource=&quot;{Binding MovieHalls, Mode=Twoway}&quot;
                          SelectedItem=&quot;{Binding MovieHallsSelected, Mode=Twoway, UpdateSourceTrigger=PropertyChanged}&quot;&gt;
                    &lt;ComboBox.Style&gt;
                        &lt;Style TargetType=&quot;ComboBox&quot;&gt;
                            &lt;Setter Property=&quot;Visibility&quot;
                                    Value=&quot;Visible&quot; /&gt;
                            &lt;Style.Triggers&gt;
                                &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected}&quot;
                                                Value=&quot;Manual Entry&quot;&gt;
                                    &lt;Setter Property=&quot;Visibility&quot;
                                            Value=&quot;Hidden&quot; /&gt;
                                &lt;/DataTrigger&gt;
                            &lt;/Style.Triggers&gt;
                        &lt;/Style&gt;
                    &lt;/ComboBox.Style&gt;
                &lt;/ComboBox&gt;
                &lt;TextBox Width=&quot;120&quot;
                            Visibility=&quot;Visible&quot;
                            Text=&quot;{Binding DataContext.TextA, RelativeSource={RelativeSource AncestorType=DataGridRow}}&quot;&gt;
                    &lt;TextBox.Style&gt;
                        &lt;Style TargetType=&quot;TextBox&quot;&gt;
                            &lt;Setter Property=&quot;Visibility&quot;
                                    Value=&quot;Hidden&quot; /&gt;
                            &lt;Style.Triggers&gt;
                                &lt;DataTrigger Binding=&quot;{Binding Path=MovieSourceSelected}&quot;
                                                Value=&quot;Manual Entry&quot;&gt;
                                    &lt;Setter Property=&quot;Visibility&quot;
                                            Value=&quot;Visible&quot; /&gt;
                                &lt;/DataTrigger&gt;
                            &lt;/Style.Triggers&gt;
                        &lt;/Style&gt;
                    &lt;/TextBox.Style&gt;
                &lt;/TextBox&gt;
            &lt;/Grid&gt;
        &lt;/DataTemplate&gt;
    &lt;/DataGridTemplateColumn.CellTemplate&gt;
&lt;/DataGridTemplateColumn&gt;

This XAML has a ComboBox that is Visible by default and set to Hidden when MovieSourceSelected is Manual Entry. The TextBox is Hidden by default and set to Visible with Manual Entry.

Regarding the Binding used for your Movie Source ComboBox, make sure it uses SelectedValue and SelectedValuePath if you are using a String as your Dependency Property:

&lt;ComboBox SelectedValue=&quot;{Binding MovieSourceSelected, Mode=TwoWay}&quot; SelectedValuePath=&quot;Content&quot;&gt;
    &lt;ComboBoxItem Content=&quot;Some option&quot; /&gt;
    &lt;ComboBoxItem Content=&quot;Manual Insertion&quot; /&gt;
    &lt;ComboBoxItem Content=&quot;Some other option&quot; /&gt;
&lt;/ComboBox&gt;

As a side note, you should not have to name your ComboBoxes (cboMovieSource and cbMovieHall) since they are working with bindings. You'd name them if you needed to access them in code-behind but from your XAML it doesn't look like you need to.

huangapple
  • 本文由 发表于 2023年5月17日 23:10:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76273588.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定