0

カスタム行追加ボタンを a に実装したいDataGrid(それは長い話です)。テンプレートにボタンを追加し、添付プロパティを定義すると、ボタンのクリックを取得できます。しかし、指定されたタイプではなく、一般的な方法で新しい行を追加することはできません。で同様のことができることはわかっていますがViewModel、テンプレートと添付プロパティでこれを行うことを検討しています。これが私の試みです。これを完了するためのアイデアはありますか?

XAML:

<Style x:Key="{x:Type DataGrid}" TargetType="{x:Type DataGrid}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGrid}">
                <Border x:Name="border">
                    <ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
                        <ScrollViewer.Template>
                            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto" />
                                        <ColumnDefinition Width="*" />
                                        <ColumnDefinition Width="Auto" />
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto" />
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="Auto" />
                                    </Grid.RowDefinitions>

                                    <Button Focusable="false"
                                            Command="{x:Static DataGrid.SelectAllCommand}" />
                                    <DataGridColumnHeadersPresenter 
                                        x:Name="PART_ColumnHeadersPresenter"
                                        Grid.Column="1" />

                                    <Grid Grid.ColumnSpan="2" Grid.Row="1">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="*"/>
                                            <RowDefinition Height="22" />
                                        </Grid.RowDefinitions>
                                        <ScrollContentPresenter 
                                                x:Name="PART_ScrollContentPresenter" />

                                        <!-- THIS IS MY CUSTOM BUTTON TO ADD NEW ROW -->
                                        <Button x:Name="PART_AddRowButton"
                                                Content="Add"/>
                                    </Grid>

                                    <ScrollBar x:Name="PART_VerticalScrollBar"/>

                                    <Grid Grid.Column="1" Grid.Row="2">
                                        <ScrollBar x:Name="PART_HorizontalScrollBar"/>
                                    </Grid>
                                </Grid>
                            </ControlTemplate>
                        </ScrollViewer.Template>
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

C#:

public class DataGridHelper {

    public static readonly DependencyProperty CanUserAddRowsProperty
        = DependencyProperty.RegisterAttached(
        "CanUserAddRows", typeof(bool), typeof(DataGridHelper),
        new FrameworkPropertyMetadata(default(bool), CanUserAddRowsChanged));

    [AttachedPropertyBrowsableForType(typeof(DataGrid))]
    public static bool GetCanUserAddRows(DependencyObject obj) {
        return (bool)obj.GetValue(CanUserAddRowsProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(DataGrid))]
    public static void SetCanUserAddRows(DependencyObject obj, bool value) {
        obj.SetValue(CanUserAddRowsProperty, value);
    }

    private static void CanUserAddRowsChanged(
        DependencyObject d,
        DependencyPropertyChangedEventArgs e) {
        var dataGrid = d as DataGrid;
        if (dataGrid == null)
            return;
        bool oldValue = (bool)e.OldValue,
            newValue = (bool)e.NewValue;
        if (newValue == oldValue)
            return;
        if (newValue) {
            dataGrid.Loaded += CanUserAddRowsDataGridLoaded;
        } else {
            dataGrid.Loaded -= CanUserAddRowsDataGridLoaded;
        }
    }

    private static void CanUserAddRowsDataGridLoaded(object sender, RoutedEventArgs e) {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null)
            return;
        if (dataGrid.Style == null)
            return;
        var rootTemplate = dataGrid.Template;
        if (rootTemplate == null)
            return;
        var scroll = rootTemplate.FindName("DG_ScrollViewer", dataGrid) as ScrollViewer;
        if (scroll == null)
            return;
        var scrollTemplate = scroll.Template;
        if (scrollTemplate == null)
            return;
        var button = scrollTemplate.FindName("PART_AddRowButton", scroll) as ButtonBase;
        if (button == null)
            return;
        if (GetCanUserAddRows(dataGrid)) {
            button.Click += AddRowClicked;
        } else {
            button.Click -= AddRowClicked;
        }
    }

    private static void AddRowClicked(object sender, RoutedEventArgs e) {
        var button = ((ButtonBase)sender);
        var parent = VisualTreeHelper.GetParent(button);
        while (!(parent is DataGrid))
            parent = VisualTreeHelper.GetParent(parent);
        var source = ((DataGrid)parent).Items.Add(...) // now what???
    }
}

ご覧のDataGridとおり、ボタンがクリックされた後にアクセスできました。しかし、次は何ですか?DataGridを強制的に表示するにはどうすればよいNewItemPlaceHolderですか?

4

1 に答える 1

0

通常、WPF では、データ オブジェクトのコレクション (できれば のような変更通知をサポートするコレクションObservableCollection) を UI コントロールにバインドします。UI コントロールに新しいアイテムを追加するのではなく、コード ビハインド/ビュー モデルのコレクションにアイテムを追加します。コレクションが変更通知をサポートしている限り、UI コントロールは自動的に更新されます。

に新しい行をDataGrid追加するには、コレクションに新しいアイテムを追加する必要があります。

dataCollection.Add(new DataType());

AttachedProperty以下を使用して、データバインドされたコレクションにアクセスできるはずです。

var dataCollection = (DataCollectionType)dataGrid.ItemsSource;

次のものも使用できると思います:

dataGrid.Items.Add(new DataType());

ただし、この方法はお勧めしません。

于 2013-07-22T12:44:55.763 に答える