我的DataGrid
有DataGridTemplateColumn
,其模板包含ComboBox
控件。我的问题是,当所选项目的显示成员太长而无法适应ComboBox
的宽度时,ComboBox
的宽度不会扩展以适应所显示的内容的宽度,如果同一ComboBox
不在DataGrid
。
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<DataGrid Height="150"
Margin="0,4,0,0"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
HorizontalAlignment="Stretch"
ColumnWidth="SizeToCells"
HeadersVisibility="Column"
AutoGenerateColumns="False"
RowHeaderWidth="0"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Entities, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=SelectedEntity}"
SelectionUnit="FullRow"
SelectionMode="Single">
<DataGrid.Resources>
<DataTemplate x:Key="TextBox_Template">
<TextBox Text="{Binding Path=Text}" Margin="2,2,2,2"/>
</DataTemplate>
<DataTemplate x:Key="ComboBox_Template">
<ComboBox Margin="2,2,2,2"
Width="Auto"
ItemsSource="{Binding Path=DataContext.AvailableActions,
Mode=OneTime,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
SelectedValue="{Binding Path=Action, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Key"
DisplayMemberPath="Value"
IsEditable="False"
IsSynchronizedWithCurrentItem="False"/>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Width="*"
CanUserReorder="False" CanUserResize="False"
CellTemplate="{StaticResource TextBox_Template}"
Header="Text Field"/>
<DataGridTemplateColumn Width="Auto"
CanUserReorder="False" CanUserResize="False"
CellTemplate="{StaticResource ComboBox_Template}"
Header="Action"/>
</DataGrid.Columns>
</DataGrid>
<Separator Margin="0,5,0,5"/>
<StackPanel Orientation="Horizontal">
<Button Content="Add Row" Margin="2,2,2,2"
Command="{Binding AddRowCommand}"/>
<Button Content="Remove Row" Margin="2,2,2,2"
Command="{Binding RemoveRowCommand}"/>
</StackPanel>
<Separator Margin="0,5,0,5"/>
<ComboBox Width="Auto"
ItemsSource="{Binding Path=AvailableActions}"
SelectedValuePath="Key"
DisplayMemberPath="Value"
IsEditable="False"
HorizontalAlignment="Left"/>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public static Dictionary<ActionType, string> AvailableActions { get; set; }
public EntityClass SelectedEntity { get; set; }
public ObservableCollection<EntityClass> Entities { get; set; }
public AddRowCommandClass AddRowCommand { get; set; }
public RemoveRowCommandClass RemoveRowCommand { get; set; }
static MainWindow()
{
AvailableActions = new Dictionary<ActionType, string>()
{
{ActionType.Accept, "Accept the text"},
{ActionType.Reject, "Reject the text"},
{ActionType.Refer, "Refer the text"},
{ActionType.Postpone, "Postpone the text"},
};
}
public MainWindow()
{
Entities = new ObservableCollection<EntityClass>()
{
new EntityClass() { Text = "First Example Text", Action = ActionType.Accept},
new EntityClass() { Text = "Second Example Text", Action = ActionType.Reject},
new EntityClass() { Text = "Third Example Text", Action = ActionType.Refer},
};
AddRowCommand = new AddRowCommandClass(this);
RemoveRowCommand = new RemoveRowCommandClass(this);
InitializeComponent();
}
public enum ActionType
{
Accept,
Reject,
Refer,
Postpone,
}
public class EntityClass
{
public string Text { get; set; }
public ActionType Action { get; set; }
}
public class AddRowCommandClass : ICommand
{
public event EventHandler CanExecuteChanged;
private MainWindow _window;
public AddRowCommandClass(MainWindow window)
{
_window = window;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_window.Entities.Add(new EntityClass() { Text = "Hello World!", Action = ActionType.Postpone });
}
}
public class RemoveRowCommandClass : ICommand
{
public event EventHandler CanExecuteChanged;
private MainWindow _window;
public RemoveRowCommandClass(MainWindow window)
{
_window = window;
}
public bool CanExecute(object parameter)
{
return _window.SelectedEntity != null;
}
public void Execute(object parameter)
{
_window.Entities.Remove(_window.SelectedEntity);
_window.SelectedEntity = null;
_window.PropertyChanged?.Invoke(_window, new PropertyChangedEventArgs("SelectedEntity"));
}
}
}
}
ComboBox
会随着所选值的大小发生变化而改变大小。DataGrid
添加新行或编辑已存在的行中的ComboBox
以选择"Postpone the text"
选项;注意ComboBox
如何更改大小以适应较大的文本,导致文本被剪裁。"Postpone the text"
,并注意ComboBox
现在如何增加宽度以适应较长的文本而不剪裁。我的问题是如何强制ComboBox
控件自动适应所选项目的宽度,并在必要时增加网格行的宽度。我希望它能够永远不会剪切所选文本,即使这意味着修改DataGrid
中特定列的宽度以适应。
答案 0 :(得分:0)
我建议将第二列的宽度从“auto”设置为“*”,就像在第一列中一样。然后设置MaxWidth,这样组合框在调整大小时就不会变大。
boolean isChecked = sharedPref.getBoolean("isChecked", false);
答案 1 :(得分:0)
使用更简单的数据网格可以重现问题:只需将一个星号大小的列放在另一个不是星号的列的前面。只要整个网格大小保持不变,布局过程就不会尝试将列缩小到左侧,以便为更多空间提供列。
以下解决方案基于https://stackoverflow.com/a/5651287/5265292
建立一些事件,指示可能需要的列调整大小,然后删除星号列宽,更新布局,恢复列宽。在我的示例中,我使用了SelectionChanged
事件,需要调度布局更新才能正常工作:
void dg1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.OriginalSource is ComboBox)
{
Dispatcher.BeginInvoke(new Action(() =>
{
dg1.Columns[0].Width = new DataGridLength();
dg1.UpdateLayout();
dg1.Columns[0].Width = new DataGridLength(1, DataGridLengthUnitType.Star);
}));
}
}
我的示例XAML包含代码背后的项目源:
<Grid x:Name="grid1">
<Grid.Resources>
<CollectionViewSource x:Key="ComboBoxItemsSource" Source="{Binding ComboItems}"/>
</Grid.Resources>
<DataGrid
x:Name="dg1"
ItemsSource="{Binding DataItems}"
AutoGenerateColumns="False"
SelectionChanged="dg1_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn
Width="*"/>
<DataGridComboBoxColumn
Header="B"
ItemsSource="{Binding Source={StaticResource ComboBoxItemsSource}}"
SelectedItemBinding="{Binding Text}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
为了完整起见,初始化和视图模型:
public MainWindow()
{
InitializeComponent();
grid1.DataContext = vm = new MyViewModel()
{
DataItems =
{
new ItemVM(),
},
ComboItems =
{
"A",
"AAAAAAAAAAAAAAAAAAAAAAA"
}
};
}
public class MyViewModel
{
private ObservableCollection<ItemVM> _DataItems = new ObservableCollection<ItemVM>();
public ObservableCollection<ItemVM> DataItems
{
get { return _DataItems; }
}
private ObservableCollection<string> _ComboItems = new ObservableCollection<string>();
public ObservableCollection<string> ComboItems
{
get { return _ComboItems; }
}
}
public class ItemVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChangedEvent([CallerMemberName]string prop = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(prop));
}
private string _Text;
public string Text
{
get { return _Text; }
set { _Text = value; RaisePropertyChangedEvent(); }
}
}
答案 2 :(得分:0)
尝试将DataTemplate直接添加到'DataGridTemplateColumn'。
我会做这样的事情:
<DataGridTemplateColumn Width="Auto"
CanUserReorder="False" CanUserResize="False"
Header="Action">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox Margin="2 2 2 2"
ItemsSource="{Binding Path=DataContext.AvailableActions,
Mode=OneTime,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
SelectedValue="{Binding Path=Action, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Key"
DisplayMemberPath="Value"
IsEditable="False"
IsSynchronizedWithCurrentItem="False"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
答案 3 :(得分:0)
您是否尝试使用HorizontalAlignment和/或HorizontalContentAlignment来对组合框进行拉伸?