C# 使用WPF C中的多个控件的组合创建自定义控件#
我想创建一个自定义控件,它应该是一个预定义控件的组合,如Textbox、Button、ListBox等 请参考以下控件(仅为示例)C# 使用WPF C中的多个控件的组合创建自定义控件#,c#,.net,wpf,xaml,custom-controls,C#,.net,Wpf,Xaml,Custom Controls,我想创建一个自定义控件,它应该是一个预定义控件的组合,如Textbox、Button、ListBox等 请参考以下控件(仅为示例) 我需要在单个自定义控件中组合控件。当我按下按钮时,我需要在ListItem中添加Textbox值,最后我需要这个控件中的列表 预期的自定义控件(仅示例) 说明: 我需要从用户那里获取字符串列表。我添加了一个文本框来获取用户的输入。我添加了一个按钮,在列表中添加文本。为了显示列表,我添加了一个列表框 我需要一个控件,它应该继承这三个控件。因此,我需要一个用于双
我需要在单个自定义控件中组合控件。当我按下按钮时,我需要在ListItem中添加Textbox值,最后我需要这个控件中的列表
预期的自定义控件(仅示例)
说明:
我需要从用户那里获取字符串列表。我添加了一个文本框来获取用户的输入。我添加了一个按钮,在列表中添加文本。为了显示列表,我添加了一个列表框
我需要一个控件,它应该继承这三个控件。因此,我需要一个用于双向绑定的ItemsSource
。如果更新了列表
,则应更新ItemSource
我在超过15个地方使用这种结构。因此,我希望将其作为自定义控件。请帮助我如何将其作为单个控件来实现
我不需要一个用户控件,我需要一个自定义控件,请帮助我
即使ItemsSource具有值,项源ViewModel集合也不会更新
假设这是您的自定义控件:
<UserControl x:Class="CustomControl.UserControl1"
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:CustomControl"
mc:Ignorable="d" >
<StackPanel Width="200" Margin="15">
<TextBox Name="txtbox"/>
<Button Content="Add"
Margin="20,0" Click="Button_Click"/>
<ListBox ItemsSource="{Binding}"
Margin="0,25">
</ListBox>
</StackPanel>
<Window x:Class="ParentControl.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:local="clr-namespace:ParentControl"
mc:Ignorable="d"
xmlns:customcontrol="clr-namespace:CustomControl;assembly=CustomControl"
Title="MainWindow" Height="350" Width="525">
<Grid>
<customcontrol:UserControl1 Name="customcontrol"></customcontrol:UserControl1>
</Grid>
这是调用自定义控件的父窗口:
<UserControl x:Class="CustomControl.UserControl1"
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:CustomControl"
mc:Ignorable="d" >
<StackPanel Width="200" Margin="15">
<TextBox Name="txtbox"/>
<Button Content="Add"
Margin="20,0" Click="Button_Click"/>
<ListBox ItemsSource="{Binding}"
Margin="0,25">
</ListBox>
</StackPanel>
<Window x:Class="ParentControl.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:local="clr-namespace:ParentControl"
mc:Ignorable="d"
xmlns:customcontrol="clr-namespace:CustomControl;assembly=CustomControl"
Title="MainWindow" Height="350" Width="525">
<Grid>
<customcontrol:UserControl1 Name="customcontrol"></customcontrol:UserControl1>
</Grid>
您有一个字符串集合,希望使用文本框中的文本更新该集合,您可以执行以下操作:
在父窗口中,将自定义控件的DataContext设置为字符串集合,如下所示:
public MainWindow()
{
InitializeComponent();
ObservableCollection<string> stringcollection = new ObservableCollection<string>();
stringcollection.Add("String 1");
stringcollection.Add("String 2");
stringcollection.Add("String 2");
stringcollection.Add("String 3");
customcontrol.DataContext = stringcollection;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var list = button.DataContext as ObservableCollection<string>;
list.Add(this.txtbox.Text.ToString());
}
public主窗口()
{
初始化组件();
ObservableCollection stringcollection=新的ObservableCollection();
stringcollection.Add(“字符串1”);
添加(“字符串2”);
添加(“字符串2”);
添加(“字符串3”);
customcontrol.DataContext=stringcollection;
}
在自定义控件返回逻辑中,向按钮单击事件添加处理程序,并执行如下操作:
public MainWindow()
{
InitializeComponent();
ObservableCollection<string> stringcollection = new ObservableCollection<string>();
stringcollection.Add("String 1");
stringcollection.Add("String 2");
stringcollection.Add("String 2");
stringcollection.Add("String 3");
customcontrol.DataContext = stringcollection;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var list = button.DataContext as ObservableCollection<string>;
list.Add(this.txtbox.Text.ToString());
}
private void按钮\u单击(对象发送者,路由目标)
{
var按钮=发送方为按钮;
var list=button.DataContext作为ObservableCollection;
list.Add(this.txtbox.Text.ToString());
}
确保字符串集合的类型为Observable collection,否则每次单击add按钮时列表框都不会更新
希望能有帮助 我为您提供了一个所需CustomControl的最小示例
控件
public class MyCustomControl : ItemsControl {
static MyCustomControl() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
private Button _addButton;
private TextBox _textBox;
private ListView _itemsView;
public override void OnApplyTemplate() {
this._addButton = this.GetTemplateChild("PART_AddButton") as Button;
this._textBox = this.GetTemplateChild("PART_TextBox") as TextBox;
this._itemsView = this.GetTemplateChild("PART_ListBox") as ListView;
this._addButton.Click += (sender, args) => {
(this.ItemsSource as IList<string>).Add(this._textBox.Text);
};
this._itemsView.ItemsSource = this.ItemsSource;
base.OnApplyTemplate();
}
public ICommand DeleteCommand => new RelayCommand(x => { (this.ItemsSource as IList<string>).Remove((string)x); });
}
公共类MyCustomControl:ItemsControl{
静态MyCustomControl(){
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl)),new FrameworkPropertyMetadata(typeof(MyCustomControl));
}
专用按钮_addButton;
专用文本框_TextBox;
私有列表视图_itemsView;
应用程序模板()上的公共重写无效{
this.\u addButton=this.GetTemplateChild(“PART\u addButton”)作为按钮;
this.\u textBox=this.GetTemplateChild(“PART\u textBox”)作为textBox;
this.\u itemsView=this.GetTemplateChild(“PART\u ListBox”)作为ListView;
这是。_addButton.Click+=(发件人,参数)=>{
(this.ItemsSource作为IList)。添加(this.\u textBox.Text);
};
this._itemsView.ItemsSource=this.ItemsSource;
base.OnApplyTemplate();
}
public ICommand DeleteCommand=>new RelayCommand(x=>{(this.ItemsSource作为IList)。Remove((string)x);});
}
模板
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox x:Name="PART_TextBox" Grid.Column="0" />
<Button x:Name="PART_AddButton" Grid.Column="1" Content="Add" Margin="20,0" />
</Grid>
<ListView ItemsSource="{TemplateBinding ItemsSource}" Grid.Row="1" Margin="0,25" x:Name="PART_ListBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding}"/>
<Button Content="X" Foreground="Red"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyCustomControl}}, Path=DeleteCommand}"
CommandParameter="{Binding}" Margin="10,0,0,0"></Button>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<local:MyCustomControl ItemsSource="{Binding Collection}"/>
RelayCommand
public class RelayCommand : ICommand
{
#region Fields
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
{
if (execute == null)
throw new ArgumentNullException(nameof(execute));
this._execute = execute;
this._canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return this._canExecute == null || this._canExecute(parameter);
}
public event EventHandler CanExecuteChanged {
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
this._execute(parameter);
}
#endregion // ICommand Members
}
公共类RelayCommand:ICommand
{
#区域字段
私有只读操作\u执行;
私有只读谓词_canExecute;
#endregion//字段
#区域构造函数
公共RelayCommand(操作执行,谓词canExecute=null)
{
if(execute==null)
抛出新ArgumentNullException(nameof(execute));
这个。_execute=execute;
这个._canExecute=canExecute;
}
#endregion//构造函数
#区域ICommand成员
[调试步骤至]
公共布尔CanExecute(对象参数)
{
返回此。_canExecute==null | |此。_canExecute(参数);
}
公共事件事件处理程序CanExecuteChanged{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
public void Execute(对象参数)
{
此._执行(参数);
}
#endregion//ICommand成员
}
用法
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBox x:Name="PART_TextBox" Grid.Column="0" />
<Button x:Name="PART_AddButton" Grid.Column="1" Content="Add" Margin="20,0" />
</Grid>
<ListView ItemsSource="{TemplateBinding ItemsSource}" Grid.Row="1" Margin="0,25" x:Name="PART_ListBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding}"/>
<Button Content="X" Foreground="Red"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyCustomControl}}, Path=DeleteCommand}"
CommandParameter="{Binding}" Margin="10,0,0,0"></Button>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<local:MyCustomControl ItemsSource="{Binding Collection}"/>
注意
不要将列表
用作项目来源。而是使用一个observateCollection
,因为它会自动通知视图