2016-06-08 4 views
4

DataGrid를 채우는 데 사용하는 사용자 정의 컨트롤이 있습니다.DataGrid를 컨트롤에서 편집하는 방법?

사용자가 하단의 빈 행을 편집하여 항목을 추가 할 수 있기를 바랍니다. (이것이 내가 itemscontrol보다는 DataGrid를 사용하는 이유입니다.) 그러나 DataGrid는 사용자가 컨트롤의 배경을 클릭하지 않는 한 마지막 항목이 편집되었음을 인식하지 못합니다. 사용자가 컨트롤이 노출하는 속성을 변경할 때 새 항목을 추가하고 싶습니다. 컨트롤의

XAML :

<UserControl x:Class="ControlTest.MyControl" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:ControlTest" 
     mc:Ignorable="d" 
     d:DesignHeight="50" d:DesignWidth="300" 
     DataContext="{Binding Path=., Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
     > 
<StackPanel Orientation="Vertical"> 
     <TextBox Text="{Binding Path=p1, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
      Width="300" 
      Height="30" 
      VerticalAlignment="Center"/> 
    <ComboBox ItemsSource="{Binding Path=DropDownValues, 
       RelativeSource={RelativeSource Mode=FindAncestor, 
       AncestorType=local:MyControl}}" 
       SelectedItem="{Binding Path=p2, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" 
       Height="30"/> 
    </StackPanel> 
</UserControl> 

CS :

public partial class MyControl : UserControl 
{ 
    private static readonly DependencyProperty DropDownValuesProperty = 
     DependencyProperty.Register(
     "DropDownValues", 
     typeof(List<String>), 
     typeof(MyControl), 
     new FrameworkPropertyMetadata(new List<String>() 
     )); 
    public List<String> DropDownValues 
    { 
     get 
     { 
      return (List<String>)GetValue(DropDownValuesProperty); 
     } 
     set 
     { 
      SetValue(DropDownValuesProperty, value); 
     } 
    } 

    public MyControl() 
    { 
     InitializeComponent(); 
    }   
} 

데이터 그리드 XAML은

<DataGrid 
     AutoGenerateColumns="False" 
     ItemsSource="{Binding objs, Mode=TwoWay}" 
     HeadersVisibility="None" 
     Margin="0,0,0.4,0" 
     CanUserAddRows="True" 
     > 
     <DataGrid.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal"/> 
      </ItemsPanelTemplate> 
     </DataGrid.ItemsPanel> 
     <DataGrid.Columns> 
      <DataGridTemplateColumn Width="300"> 
       <DataGridTemplateColumn.CellTemplate> 
        <DataTemplate DataType="local:Measure"> 
         <local:MyControl 
          DataContext="{Binding ., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
          DropDownValues= 
         "{Binding DataContext.list, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" 
          Width="300" 
         /> 
        </DataTemplate> 
       </DataGridTemplateColumn.CellTemplate> 
      </DataGridTemplateColumn> 
     </DataGrid.Columns> 
    </DataGrid> 

나는이 작품을 만들 수 및/또는 할 수있는 더 좋은 방법이 이?

+0

당신은 무엇을 의미합니까? 사용자가 컨트롤의 배경을 클릭하지 않으면 마지막 항목이 편집되었음을 알지 못합니다. 나는 기본 동작이 무엇을 의미합니까 ??? – Vishal

+0

@Vishal 컨트롤이없는 기본 동작은 포커스가없는 필드가 새로 추가되면 포커스가 사라지는 것입니다. 이것은 내가 컨트롤을 가지고있을 때 관찰했던 것과 다소 비슷하지만 편집하는 컨트롤 안에있는 컨트롤 중 하나 일 때 셀에 포커스가 있다는 것을 데이터 격자가 이해하지 못한다. 그래서 배경을 클릭 할 때까지 새로운 아이템이 추가되지 않는다. 제어. – Taemyr

+0

Datagrid가 마지막 항목이 편집되었음을 인식하지 못한다는 것을 어떻게 알 수 있습니까? 'Items'에 직접 또는'objs'에 추가하고 있습니까? – M312V

답변

1

UI에 objs 컬렉션에 대한 변경 사항이 통지되지 않는 문제가 있습니까? 내가 무엇을 할 것이라고 objs objs 관찰 가능한 컬렉션을 만들 수있는 모든보기 모델 설정 시도하십시오. 또한 obj가 관찰 가능한 INotifyPropertyChanged 컬렉션이며, p1과 p2가 둘 다 설정되면 OnPorpertyChanged를 발생시키는 지 확인합니다. 내가 좋아하는 것

public ObservableCollection<YourObject> objs 

public class YourObject : INotifyPropertyChanged 
{ 
    protected void OnPropertyChanged(string Name) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(Name)); 
     } 
    } 

    private string _p1; 
    public string p1 
    { 
     get { return _p1; } 
     set 
     { 
      if (_p1 != value) 
      { 
       _p1 = value; 
       OnPropertyChanged("p1"); 
      } 
     } 
    } 
    private string _p2; 
    public string p2 
    { 
     get { return _p2; } 
     set 
     { 
      if (_p2 != value) 
      { 
       _p2 = value; 
       OnPropertyChanged("p2"); 
      } 
     } 
    } 
} 
+0

문제는 컨트롤의 항목을 변경할 때 새 항목이 컬렉션에 추가되지 않는다는 것입니다. - 외부에서 컬렉션을 변경하면 DataGrid가 업그레이드되어 DataGrid에서 컬렉션에 항목을 추가하게되지만 컨트롤의 배경을 클릭해야합니다. 새 항목을 만들고 추가해야합니다. 컨트롤의 항목을 편집하기 시작합니다. – Taemyr

+0

그리고 컬렉션은 이미 INotifyPropertyChanged를 구현하는 클래스의 관찰 가능 콜렉션입니다. – Taemyr

+0

InvalidateArrange 및/또는 InvalidateMeasure를 시도하십시오. – M312V

2

당신에게 그 일을 다른 방법 제안 : 귀하의 데이터 그리드에 CanUserAddRows=false을 설정

을 한 후 수동으로 데이터 그리드 인에 ObservableCollection<Something> 행을 추가 하게되다.

당신의 XAML 파일에서 : 코드 숨김에서 다음

<DataGrid x:Name="myDataGrid" CellEditEnding="DataGrid_CellEditEnding" .....> 
    <!--Some Code--> 
</DataGrid> 

:

private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) 
{ 
    myDataGrid.CommitEdit(); 
} 

또는

당신은 아직도 당신이 따라 접근 방법에 관심이 있다면

아무 것도 이해하지 못하면 n 자유롭게 물어보십시오.

업데이트 같은 방법 다음과 같은 경우

: 당신이 시도 할 수있는 데이터 그리드의 시작 편집 이벤트에서

:

private void DataGrid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e) 
{ 
    if ((selectedRow as DataGridRow).Item.ToString() != "{NewItemPlaceholder}") 
    { 
     //Here you can add the code to add new item. I don't know how but you should figure out a way 
    } 
} 

참고 :는 위에서 언급 한 코드가 아닌를 테스트를 거쳤습니다.

는 또한 당신을 제안 :

는 데이터 그리드를 사용하지 않습니다. 대신 ListBox를 사용하십시오.왜냐하면, 데이터를 추가하려고하기 때문입니다. 현재는 정렬, 검색 및 컬럼 재정렬 작업을 수행 할 필요가 없습니다. 이러한 시나리오에서 ListBox는 DataGrid보다 경량 컨트롤이므로 유용합니다. 여기에 샘플이 있습니다 : https://drive.google.com/open?id=0B5WyqSALui0bTXFGZWxQUWVRdkU

+0

CellEditEnding에서 CommitEdit을 설정해도 컨트롤의 필드를 변경할 때 새 항목이 만들어지지 않았습니다. 그것은 컨트롤의 배경을 두 번 클릭하면 stackoverflow 예외가 발생하지 않습니다. – Taemyr

+0

컨트롤에 컬렉션을 알리지 않고 수동으로 행을 추가하는 방법이 있습니까? – Taemyr

+0

@Taemyr 제 답변을 보시기 바랍니다. – Vishal

관련 문제