【问题标题】:Datagrid combobox getting relativsource to workingDatagrid组合框让relativsource工作
【发布时间】:2016-09-20 16:02:54
【问题描述】:

我正在使用 WPF 组合框来过滤项目,但我决定将它放在我的数据网格中,但我无法让它工作可能在他们的我只能让它在数据网格之外工作。

我认为问题是因为

RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, or ElementName=win

在数据网格内部不支持,所以我如何让它工作。

这是我得到的错误

System.Windows.Data 错误:4:找不到与引用“RelativeSource FindAncestor,AncestorType='System.Windows.Window',AncestorLevel='1''的绑定源。 BindingExpression:Path=SelectedParam;数据项=空;目标元素是'ComboBox'(名称='Krydsmålbox');目标属性是“SelectedValue”(类型“对象”)

<DataGrid x:Name="hjuldata" 
ItemsSource="{Binding Source={StaticResource cvsTasks}}"
CanUserAddRows="False"  BorderBrush="#FF303030" Foreground="#FF00FB0B" Background="#FF303030" AutoGenerateColumns="False" GridLinesVisibility="None" VerticalAlignment="Center" Height="644" Canvas.Left="20" Canvas.Top="257" Width="1250" >
 <DataGrid.Columns>
 <DataGridTextColumn Binding="{Binding Krydsmålet}">
 <DataGridTextColumn.HeaderTemplate>
     <DataTemplate>
        <ContentPresenter Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
     </DataTemplate>
 </DataGridTextColumn.HeaderTemplate>
  <DataGridTextColumn.Header>
      <ComboBox   x:Name="Krydsmålbox" Foreground="#FFEAEAEA" Background="#FF303030" FontSize="12" 
                  Style="{StaticResource ComboBoxTest2}"  ItemTemplate="{StaticResource cmbTemplate2}" 
                  ItemsSource="{Binding}"  SelectedValuePath="Krydsmålene"
                  SelectedValue = "{Binding SelectedParam, RelativeSource={RelativeSource FindAncestor, 
                  AncestorType={x:Type Window}},UpdateSourceTrigger=PropertyChanged}" BorderBrush="#FF303030" Height="40" DockPanel.Dock="Top" IsSynchronizedWithCurrentItem="True" SelectionChanged="Krydsmålbox_SelectionChanged" Canvas.Left="813" Canvas.Top="96" Width="146"/>
 </DataGridTextColumn.Header>
 </DataGridTextColumn>

数据模板

<DataTemplate x:Key="cmbTemplate2">
    <WrapPanel Margin="0 5 0 5" Height="30">
        <Image Width="10" Height="20" Stretch="Fill" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,15,0"/>
        <Label Content="{Binding Krydsmålene}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="16" Foreground="#FF00FB0B"/>
    </WrapPanel>
</DataTemplate>

CS

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public string SelectedParam
{
    get { return _selectedParam; }
    set
    {
        _selectedParam = value; OnPropertyChanged("SelectedParam");
        if (_selectedParam == "Krydsmål") { BindData(); } else { hjuldata.ItemsSource = FilterKategori().Tables[0].DefaultView; ; }
    }
}

public DataSet DTbindkryds()
{
    Data = @"SELECT Krydsmålene FROM Data.Krydsmål";
    //SQL statement to fetch entries from Krydsmål
    DataSet dsdata = new DataSet();

    //Open SQL Connection
    using (conn = new SqlConnection(connStrings))
    {
        conn.Open();

        //Initialize command object
        using (conn = new SqlConnection(connStrings))
        using (cmd = new SqlCommand(Data, conn))
        {
            SqlDataAdapter adapters = new SqlDataAdapter(cmd);

            //Fill the result set
            adapters.Fill(dsdata);
            conn.Close();
        }
    }
    return dsdata;
}

private void bindkrydsmål()
{
    Krydsmålbox.ItemsSource = DTbindkryds().Tables[0].DefaultView;
}

【问题讨论】:

  • 为什么不为网格定义一个数据模板并定义一个数据类型,以便您可以将选定的值直接绑定到某个属性?
  • 因为我无法让 datatemplate 与 header 属性一起使用
  • 有可能。搜索 wpf datagrid header 模板
  • 我曾尝试使用&lt;DataGridTextColumn.Header&gt; &lt;DataTemplate&gt; &lt;ComboBox &lt;/DataTemplate&gt;,然后它在我的组合框中显示 system.windows.datatemplate 并且我的组合框在当前上下文中不存在
  • 问题在于你的Binding,你的Path应该指向DataContext.SelectedParam

标签: c# wpf combobox datagrid


【解决方案1】:

不要在 Header 属性中使用 DataTemplate,像这样在 HeaderTemplate 中使用它:

<DataGridTextColumn.HeaderTemplate>
  <DataTemplate>
    <ComboBox x:Name="Krydsmålbox" Foreground="#FFEAEAEA" Background="#FF303030" FontSize="12" 
    Style="{StaticResource ComboBoxTest2}"  ItemTemplate="{StaticResource cmbTemplate2}" 
    ItemsSource="{Binding}"  SelectedValuePath="Krydsmålene"
    SelectedValue = "{Binding SelectedParam, RelativeSource={RelativeSource FindAncestor, 
    AncestorType={x:Type Window}},UpdateSourceTrigger=PropertyChanged}" BorderBrush="#FF303030" Height="40" DockPanel.Dock="Top" IsSynchronizedWithCurrentItem="True" SelectionChanged="Krydsmålbox_SelectionChanged" Canvas.Left="813" Canvas.Top="96" Width="146"/>
  </DataTemplate>
</DataGridTextColumn.HeaderTemplate>

一旦你这样做了,ElementNameRelativeSource 都应该可以工作。

如果您希望能够在后面的代码中按名称引用组合框,您可以使用ContentPresenter 来呈现您想要的任何类型的 Header(我认为默认的 HeaderTemplate 是 TextBlock 而不是 ContentPresenter) :

<DataGridTextColumn.HeaderTemplate>
  <DataTemplate>
    <ContentPresenter Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
  </DataTemplate>
</DataGridTextColumn.HeaderTemplate>
<DataGridTextColumn.Header>
  <ComboBox x:Name="Krydsmålbox" Foreground="#FFEAEAEA" Background="#FF303030" FontSize="12" 
      Style="{StaticResource ComboBoxTest2}"  ItemTemplate="{StaticResource cmbTemplate2}" 
      ItemsSource="{Binding}"  SelectedValuePath="Krydsmålene"
      SelectedValue = "{Binding SelectedParam, RelativeSource={RelativeSource FindAncestor, 
      AncestorType={x:Type Window}},UpdateSourceTrigger=PropertyChanged}" BorderBrush="#FF303030" Height="40" DockPanel.Dock="Top" IsSynchronizedWithCurrentItem="True" SelectionChanged="Krydsmålbox_SelectionChanged" Canvas.Left="813" Canvas.Top="96" Width="146"/>
</DataGridTextColumn.Header>

【讨论】:

  • 它告诉我 Krydsmålbox 在当前上下文中不存在
  • @ominidata 您是否尝试使用后面代码中的组合框?如果是这样,那么是的,它将不再可访问。
  • @ominidata 我添加了一个示例,允许您在后面引用它的代码(通过 ContentPresenter)
  • 解决了但我仍然收到错误Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=SelectedParam; DataItem=null; target element is 'ComboBox' (Name='Krydsmålbox'); target property is 'SelectedValue' (type 'Object')
  • @ominidata 奇怪,我无法重现您的问题。您的对话框的框架版本和 XAML 的其余部分是什么?
【解决方案2】:

我认为WPF 开发人员的真正问题非常小且频繁。更改您的 SelectedValue 绑定,如下所示:

    SelectedValue = "{Binding DataContext.SelectedParam, RelativeSource={RelativeSource FindAncestor, 
                       AncestorType={x:Type Window}},UpdateSourceTrigger=PropertyChanged}"

由于您没有给出如何为window 分配DataContext 的代码,因此这是一个可行的检查选项。如果它是相同的window 类,那么绑定应该在没有DataContext. 的情况下工作,但是datagrid 内部不支持RelativeSource 绑定的假设是错误的。只要元素在控件的VisualTree 中并且您的组合框在窗口的可视化树中,RelativeSource 就可以工作。对吧?

为了节省证明事实的时间,下面是演示(通过最大限度地重复使用代码并在 DataGrid 的标头中使用模板创建)。

XAML:

<DataGrid ItemsSource="{Binding Items}" CanUserAddRows="False" AutoGenerateColumns="False" VerticalAlignment="Stretch" >
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding DeviceState}">                
            <DataGridTextColumn.Header>
                <ComboBox HorizontalAlignment="Stretch" Width="200" SelectedValuePath="DeviceState"
                                ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Window},Path=DataContext.Items}"
                                SelectedValue = "{Binding SelectedParam, RelativeSource={RelativeSource FindAncestor, 
                                AncestorType={x:Type Window}}}" >
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <Label Content="{Binding DeviceState}" VerticalAlignment="Center" HorizontalAlignment="Stretch"/>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>                                    
            </DataGridTextColumn.Header>
        </DataGridTextColumn>
        <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="200"/>
    </DataGrid.Columns>
</DataGrid>

代码隐藏:

 public MainWindow()
    {
        Items = new List<Device>();
        Items.Add(new Device() { Name = "Device1",DeviceState = 1 });
        Items.Add(new Device() { Name = "Device2", DeviceState = 2 });
        Items.Add(new Device() { Name = "Device3", DeviceState = 3 });
        Items.Add(new Device() { Name = "Device4", DeviceState = 4 });
        Items.Add(new Device() { Name = "Device5", DeviceState = 5 });
        InitializeComponent();
        
    }

    public List<Device> Items { get; set; }

    private string _selectedParam = "1";
    public string SelectedParam
    {
        get { return _selectedParam; }
        set
        {
            _selectedParam = value; 
            UpdateProperty("SelectedParam");                
        }
    }

输出:

正如您在输出中看到的那样,datagrid 的标头中的 combobox 默认情况下具有选定项,并且使用 relativesource 绑定反映了这一点,正如您在上面的 XAML 中看到的那样。

【讨论】:

    猜你喜欢
    • 2015-10-23
    • 2014-02-03
    • 2017-08-20
    • 2013-09-30
    • 1970-01-01
    • 2011-03-02
    • 2018-01-17
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多