바인딩 항목WPF 데이터 그리드의 ComboBox 열 원본
두 개의 간단한 모델 수업과 하나의 뷰 모델 수업이 있습니다.
public class GridItem
{
public string Name { get; set; }
public int CompanyID { get; set; }
}
public class CompanyItem
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ViewModel
{
public ViewModel()
{
GridItems = new ObservableCollection<GridItem>() {
new GridItem() { Name = "Jim", CompanyID = 1 } };
CompanyItems = new ObservableCollection<CompanyItem>() {
new CompanyItem() { ID = 1, Name = "Company 1" },
new CompanyItem() { ID = 2, Name = "Company 2" } };
}
public ObservableCollection<GridItem> GridItems { get; set; }
public ObservableCollection<CompanyItem> CompanyItems { get; set; }
}
...간단한 창:
<Window x:Class="DataGridComboBoxColumnApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GridItems}" >
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridComboBoxColumn ItemsSource="{Binding CompanyItems}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValueBinding="{Binding CompanyID}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Window의 Model(보기 모델)로됩니다.DataContext
App.xaml.cs 파일:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
ViewModel viewModel = new ViewModel();
window.DataContext = viewModel;
window.Show();
}
}
보다시피 제가 설정한 것은ItemsSource
데이터 그리드의 위치를 지정할 수 있습니다.GridItems
View Model의 컬렉션입니다.이 부품이 작동하면 이름이 "Jim"인 단일 그리드 선이 표시됩니다.
또한 다음을 설정합니다.ItemsSource
에서 "콤보박스"로합니다.CompanyItems
View Model의 컬렉션입니다.작동하지 .콤보 상자가 비어 있고 디버거 출력 창에 다음과 같은 오류 메시지가 표시됩니다.
시스템. 윈도우.데이터 오류: 2: 대상 요소에 대한 지배 FrameworkElement 또는 FrameworkContentElement를 찾을 수 없습니다.바인딩 식:경로=회사Items; DataItem=hostname; 대상 요소는 'DataGridComboBoxColumn'(HashCode=28633162)이고 대상 속성은 'Items'입니다.Source'(유형 ')IEnumberable')
가 WPF를 기대한다고 합니다.CompanyItems
의 GridItem
사실은 그렇지 않습니다, 그래서 바인딩이 실패하는 것입니다.
이미 작업을 시도했습니다.RelativeSource
그리고.AncestorType
예:
<DataGridComboBoxColumn ItemsSource="{Binding CompanyItems,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValueBinding="{Binding CompanyID}" />
그러나 디버거 출력에 또 다른 오류가 발생합니다.
시스템. 윈도우.데이터 오류: 4: '상대 원본 찾기 조상, 조상' 참조로 바인딩할 소스를 찾을 수 없습니다.='System'을 입력합니다.창문들.창', 상위 수준='1'.바인딩 식:경로=회사Items; DataItem=hostname; 대상 요소는 'DataGridComboBoxColumn'(HashCode=1150788)이고 대상 속성은 'Items'입니다.Source'(유형 ')IEnumberable')
질문:.항목을 바인딩하는 방법회사의 데이터 그리드 콤보박스 열 출처View 모델의 항목 모음?가능할까요?
미리 도와주셔서 감사합니다!
아래 DataGridComboBoxColumn xaml이 작동하는지 확인하십시오.
<DataGridComboBoxColumn
SelectedValueBinding="{Binding CompanyID}"
DisplayMemberPath="Name"
SelectedValuePath="ID">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ItemsSource" Value="{Binding Path=DataContext.CompanyItems, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
여기에서 당면한 문제에 대한 다른 솔루션을 찾을 수 있습니다.WPF 데이터 그리드와 함께 콤보 상자 사용
에 대한 MSDN의 문서에는 정적 리소스, 정적 코드 또는 콤보 상자 항목의 인라인 컬렉션만ItemsSource
:
드롭다운 목록을 채우려면 먼저 항목을 설정합니다.다음 옵션 중 하나를 사용하여 ComboBox의 소스 속성을 지정합니다.
- 정적 리소스입니다.자세한 내용은 정적 리소스 마크업 확장을 참조하십시오.
- X: 정적 코드 엔티티입니다.자세한 내용은 x: 정적 마크업 확장을 참조하십시오.
- ComboBoxItem 유형의 인라인 컬렉션입니다.
올바르게 이해한 경우 DataContext 속성에 바인딩할 수 없습니다.
그리고 실제로:내가 만들때CompanyItems
ViewModel의 정적 속성...
public static ObservableCollection<CompanyItem> CompanyItems { get; set; }
View Model이 있는 네임스페이스를 창에 추가...
xmlns:vm="clr-namespace:DataGridComboBoxColumnApp"
바인딩을 ...로 변경합니다.
<DataGridComboBoxColumn
ItemsSource="{Binding Source={x:Static vm:ViewModel.CompanyItems}}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValueBinding="{Binding CompanyID}" />
그러면 작동합니다.하지만 아이템을 갖는 것정적 속성으로 소스를 사용하는 것이 가끔은 괜찮을지도 모르지만 항상 원하는 것은 아닙니다.
올바른 해결책은 다음과 같습니다.
<Window.Resources>
<CollectionViewSource x:Key="ItemsCVS" Source="{Binding MyItems}" />
</Window.Resources>
<!-- ... -->
<DataGrid ItemsSource="{Binding MyRecords}">
<DataGridComboBoxColumn Header="Column With Predefined Values"
ItemsSource="{Binding Source={StaticResource ItemsCVS}}"
SelectedValueBinding="{Binding MyItemId}"
SelectedValuePath="Id"
DisplayMemberPath="StatusCode" />
</DataGrid>
위의 레이아웃은 저에게 완벽하게 잘 작동하며, 다른 사람들에게도 잘 작동할 것입니다.이러한 설계 선택은 어디에서도 잘 설명되지 않지만 의미가 있습니다.그러나 미리 정의된 값이 있는 데이터 열이 있는 경우에는 일반적으로 런타임 동안 값이 변경되지 않습니다. 성하기를 것.CollectionViewSource
일단 데이터를 초기화하는 것이 합리적입니다.또한 조상을 찾고 조상의 데이터 컨텍스트를 바인딩하는 긴 바인딩을 제거합니다(항상 잘못된 것으로 느껴짐).
저는 이 구속력에 어려움을 겪고 있는 다른 사람들을 위해 이것을 여기에 남깁니다. 그리고 더 나은 방법이 있는지 궁금했습니다. (이 페이지가 여전히 검색 결과에 분명히 나오고 있기 때문에, 그것이 제가 여기에 온 방법입니다.)
저는 이 질문이 1년이 넘었다는 것을 알지만, 저는 비슷한 문제를 다루다가 우연히 발견했고 미래의 여행자(또는 저 자신)에게 도움이 될 수도 있을 때를 대비해 다른 잠재적인 해결책을 공유하려고 생각했습니다.나중에 이것을 잊어버리고 내 책상 위에 있는 가장 가까운 물체의 비명과 던지기 사이에서 스택 오버플로에 털썩 주저앉는 내 자신을 발견할 때)
제 경우에는 DataGridComboBoxColumn 대신 DataGridTemplateColumn을 사용하여 원하는 효과를 얻을 수 있었습니다. 이는 다음 스니펫과 같습니다.[자세한 내용:사용하고 있습니다.NET 4.0, 그리고 제가 읽은 바로는 DataGrid가 많은 발전을 이루었다고 생각합니다. 따라서 이전 버전을 사용하는 경우 YMMV]
<DataGridTemplateColumn Header="Identifier_TEMPLATED">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox IsEditable="False"
Text="{Binding ComponentIdentifier,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Path=ApplicableIdentifiers, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding ComponentIdentifier}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
루키릭옳다니, 다니합습사용이다,.DataGridTemplateColumn
에 DataGridComboBoxColumn
을 제공합니다.
가다넣, 는을것것을 .CompanyItem
에서 직접할수목에서 수 있는 GridItem
당신은 그것을 제거할 수 있습니다.RelativeSource
.
IMHO, 이것은 당신에게 매우 깨끗한 해결책을 줍니다.
XAML:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding GridItems}" >
<DataGrid.Resources>
<DataTemplate x:Key="CompanyDisplayTemplate" DataType="vm:GridItem">
<TextBlock Text="{Binding Company}" />
</DataTemplate>
<DataTemplate x:Key="CompanyEditingTemplate" DataType="vm:GridItem">
<ComboBox SelectedItem="{Binding Company}" ItemsSource="{Binding CompanyList}" />
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" />
<DataGridTemplateColumn CellTemplate="{StaticResource CompanyDisplayTemplate}"
CellEditingTemplate="{StaticResource CompanyEditingTemplate}" />
</DataGrid.Columns>
</DataGrid>
모델 보기:
public class GridItem
{
public string Name { get; set; }
public CompanyItem Company { get; set; }
public IEnumerable<CompanyItem> CompanyList { get; set; }
}
public class CompanyItem
{
public int ID { get; set; }
public string Name { get; set; }
public override string ToString() { return Name; }
}
public class ViewModel
{
readonly ObservableCollection<CompanyItem> companies;
public ViewModel()
{
companies = new ObservableCollection<CompanyItem>{
new CompanyItem { ID = 1, Name = "Company 1" },
new CompanyItem { ID = 2, Name = "Company 2" }
};
GridItems = new ObservableCollection<GridItem> {
new GridItem { Name = "Jim", Company = companies[0], CompanyList = companies}
};
}
public ObservableCollection<GridItem> GridItems { get; set; }
}
ComboBox가 다음에 바인딩하려고 합니다.GridItem[x].CompanyItems
존재하지 않는.
RelativeBinding이 가깝지만 다음에 바인딩해야 합니다.DataContext.CompanyItems
Window 때문에.회사 항목이 존재하지 않습니다.
내가 사용하는 가장 기본적인 방법은 텍스트 블록과 콤보 상자를 동일한 속성에 바인딩하고 이 속성은 notifyPropertyChanged를 지원해야 합니다.
나는 부모 보기 데이터 컨텍스트에 바인딩하기 위해 상대적 리소스를 사용했는데, 이는 바인딩에서 데이터 그리드가 사용한 개체에서 검색하기 때문에 바인딩에서 데이터 그리드 레벨을 상승시키는 사용자 제어입니다.
<DataGridTemplateColumn Header="your_columnName">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.SelectedUnit.Name, Mode=TwoWay}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox DisplayMemberPath="Name"
IsEditable="True"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.UnitLookupCollection}"
SelectedItem="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Path=DataContext.SelectedUnit, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValue="{Binding UnitId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Id" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
이것은 저에게 효과가 있습니다.
<DataGridTemplateColumn Width="*" Header="Block Names">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
VerticalContentAlignment="Center"
ItemsSource="{Binding DataContext.LayerNames,
RelativeSource={RelativeSource Findancestor,
AncestorType={x:Type Window}}}"
SelectedItem="{Binding LayerName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
언급URL : https://stackoverflow.com/questions/5409259/binding-itemssource-of-a-comboboxcolumn-in-wpf-datagrid
'programing' 카테고리의 다른 글
요소를 수평으로 중앙에 배치하려면 어떻게 해야 합니까? (0) | 2023.05.05 |
---|---|
List는 삽입 순서를 보장합니까? (0) | 2023.05.05 |
DateTime 속성의 기본값을 DateTime으로 설정하는 중입니다.이제 시스템 안으로 들어갑니다.ComponentModel 기본값 특성입니다. (0) | 2023.04.25 |
매개 변수를 Bash 함수에 전달합니다. (0) | 2023.04.25 |
여러 조건이 있는 Bash if 문이 오류를 발생시킵니다. (0) | 2023.04.25 |