C# 如何在使用点将数据网格分配给WPF中的用户控件?
我试图为典型的双列表情况定义一个用户控件(其中有两个并排的项目列表和按钮控件,用于将所选项目从一个转移到另一个)。我对WPF不是很精通——我所学到的大部分知识都是通过类似这样的网站获得的。我已经了解到,我可以为控件创建自定义依赖属性,这样我就可以推迟控件中项目(按钮、文本框等)的绑定,直到控件实际使用为止,这非常好。然而,对于我的控制,我将有两个列表(可能是DataGrids,因为我的大部分代码都涉及到它们),但它们需要的不仅仅是绑定,所以我想做的是这样的:C# 如何在使用点将数据网格分配给WPF中的用户控件?,c#,wpf,data-binding,datagrid,user-controls,C#,Wpf,Data Binding,Datagrid,User Controls,我试图为典型的双列表情况定义一个用户控件(其中有两个并排的项目列表和按钮控件,用于将所选项目从一个转移到另一个)。我对WPF不是很精通——我所学到的大部分知识都是通过类似这样的网站获得的。我已经了解到,我可以为控件创建自定义依赖属性,这样我就可以推迟控件中项目(按钮、文本框等)的绑定,直到控件实际使用为止,这非常好。然而,对于我的控制,我将有两个列表(可能是DataGrids,因为我的大部分代码都涉及到它们),但它们需要的不仅仅是绑定,所以我想做的是这样的: <MyUserCont
<MyUserControl . . . .>
<DataGrid . . . .>
<DataGrid . . . .>
</MyUserControl>
但我不知道该怎么做。我认为可能有某种方法可以使用ContentControls作为数据网格的替代,然后以某种方式将数据网格链接回usercontrol中的ContentControls,但我并不真正理解ContentControls,而且我发现使用它们的示例似乎都不适用于我想要做的事情
有人能给我指出正确的方向吗?谢谢。我做了更多的研究,发现了一种很有希望的方法,如下所示: 我做了一个小的概念验证项目,效果很好,所以我想在这里分享一下。它使用Galasoft的MVVM轻型框架 我创建了一个带有textblock、ContentControl和按钮的用户控件:
<UserControl x:Class="DataGridInUserControlDemo.UserControls.DGPlusUC"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
mc:Ignorable="d ignore"
x:Name="ControlRoot">
<Grid DataContext="{Binding ElementName=ControlRoot}" Margin="10, 10, 10, 10" MinHeight="300" MinWidth="300">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=BannerText}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20"/>
<ContentControl Grid.Row="1" Content="{Binding Path=InnerContent}" />
<Button Grid.Row="2" x:Name="DemoButton" Content="{Binding Path=ButtonContent}" Command="{Binding Path=ButtonCommand}" Width="75" Height="25" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</UserControl>
这是主窗口的XAML:
<Window x:Class="DataGridInUserControlDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
xmlns:demo="clr-namespace:DataGridInUserControlDemo.UserControls"
mc:Ignorable="d ignore"
Height="400"
Width="400"
Title="MVVM Light Application"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<demo:DGPlusUC BannerText="{Binding UCTitle}" ButtonContent="{Binding ButtonText}" ButtonCommand="{Binding ButtonCommand}" HorizontalAlignment="Center" VerticalAlignment="Center">
<demo:DGPlusUC.InnerContent>
<Grid DataContext="{Binding Main, Source={StaticResource Locator}}">
<DataGrid ItemsSource="{Binding Path=DataItems}" AutoGenerateColumns="True" />
</Grid>
</demo:DGPlusUC.InnerContent>
</demo:DGPlusUC>
</Grid>
</Window>
最后,以下是结果:
您的代码可能并不“需要比绑定多得多”-如果您的数据绑定到viewmodel,那么该模型可以实现您所需的任何级别的复杂性,并通过绑定将状态更改反映回UI。感谢您的评论,但我如何处理列数和大小、标题、,视图模型中的列格式等?我知道我可以自动生成列,但这并不能让我对它们有太多的控制,而且这些关注点大多与视图相关,因此它们似乎不太可能在视图模型中完成。你的观点很好,我真的无法判断你的问题,但对我来说,viewmodel应该负责列的数量是有道理的。通过绑定实现它。我同意格式是视图真正关心的问题,因此我将在xaml中定义所有列,但让viewmodel控制它们的可见性。
<Window x:Class="DataGridInUserControlDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
xmlns:demo="clr-namespace:DataGridInUserControlDemo.UserControls"
mc:Ignorable="d ignore"
Height="400"
Width="400"
Title="MVVM Light Application"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<demo:DGPlusUC BannerText="{Binding UCTitle}" ButtonContent="{Binding ButtonText}" ButtonCommand="{Binding ButtonCommand}" HorizontalAlignment="Center" VerticalAlignment="Center">
<demo:DGPlusUC.InnerContent>
<Grid DataContext="{Binding Main, Source={StaticResource Locator}}">
<DataGrid ItemsSource="{Binding Path=DataItems}" AutoGenerateColumns="True" />
</Grid>
</demo:DGPlusUC.InnerContent>
</demo:DGPlusUC>
</Grid>
</Window>
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using DataGridInUserControlDemo.Model;
using System.Windows.Input;
using System.Collections.ObjectModel;
namespace DataGridInUserControlDemo.ViewModel
{
public class MainViewModel : ViewModelBase
{
private readonly IDataModel theModel;
private ObservableCollection<DataItem> _DataItems;
public ObservableCollection<DataItem> DataItems
{
get
{
return _DataItems;
}
set
{
if (_DataItems == value)
{
return;
}
var oldValue = _DataItems;
_DataItems = value;
RaisePropertyChanged(() => DataItems, oldValue, value, true);
}
}
private string _ButtonText = "First";
public string ButtonText
{
get
{
return this._ButtonText;
}
set
{
if (this._ButtonText == value)
{
return;
}
var oldValue = this._ButtonText;
this._ButtonText = value;
RaisePropertyChanged(() => ButtonText, oldValue, value, true);
}
}
private string _UCTitle = string.Empty;
public string UCTitle
{
get
{
return this._UCTitle;
}
set
{
if (this._UCTitle == value)
{
return;
}
var oldValue = this._UCTitle;
this._UCTitle = value;
RaisePropertyChanged(() => UCTitle, oldValue, value, true);
}
}
private ICommand _ButtonCommand;
public ICommand ButtonCommand
{
get
{
return this._ButtonCommand;
}
set
{
if (this._ButtonCommand == value)
{
return;
}
var oldValue = this._ButtonCommand;
this._ButtonCommand = value;
RaisePropertyChanged(() => ButtonCommand, oldValue, value, true);
}
}
public MainViewModel(IDataModel model)
{
this.theModel = model;
this._UCTitle = "DataGrid in User Control Demo";
this._DataItems = new ObservableCollection<DataItem>(this.theModel.SomeData);
this._ButtonCommand = new RelayCommand(this.ButtonCmd, () => { return true; }) ;
}
private void ButtonCmd()
{
if (this.ButtonText == "First")
{
this.ButtonText = "Second";
}
else
{
this.ButtonText = "First";
}
}
}
}