托管在 2 个控件中的按钮的绑定问题
Binding issue with button hosted in 2 controls
嗨,我知道这是很多代码,但我希望有人能帮助我或指出正确的方向,即使在命令和任务上使用断点,我的导出到 csv 命令也没有触发,所以我假设它在某处的数据上下文中找不到,其他一切都有效,数据被填充,编辑按钮有效。
所以我有 2 UserControl
s TitleControl
和 BillOfMaterialsControl
,我在标题控件中托管了一些按钮,而这是在材料清单控件中托管的,看来我的按钮无法使用正在托管在另一个控件中。
我在输出中收到此错误 window:
System.Windows.Data Error: 40 : BindingExpression path error: 'ExportButtonCommand' property not found on 'object' ''TitleControl' (Name='')'. BindingExpression:Path=ExportButtonCommand; DataItem='TitleControl' (Name=''); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')
非常感谢任何帮助。
BillOfMaterials.xaml控制
<UserControl x:Class="Bright_Instruments.Controls.BillOfMaterialsControl"
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:Bright_Instruments.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" xmlns:controls="clr-namespace:Bright_Instruments.Controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:TitleControl Grid.Column="0" Badge="{Binding Badge, RelativeSource={RelativeSource AncestorType=UserControl}}" Grid.Row="0" Margin="5" Text="PARTS LIST" Icon="{iconPacks:PicolIcons Kind=ListNumbered}">
<controls:TitleControl.TitleContent>
<StackPanel Margin="0" HorizontalAlignment="Right" Orientation="Horizontal">
<Button ToolTip="Print parts list" Margin="5" HorizontalAlignment="Right" Style="{DynamicResource MahApps.Styles.Button.Chromeless}">
<Button.Content>
<iconPacks:PackIconEntypo Kind="Print"/>
</Button.Content>
</Button>
<Button Margin="5"
Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}" ToolTip="Export parts list to .csv" HorizontalAlignment="Right" Style="{DynamicResource MahApps.Styles.Button.Chromeless}">
<Button.Content>
<iconPacks:PackIconFontAwesome Kind="FileCsvSolid"/>
</Button.Content>
</Button>
<Button Margin="5" ToolTip="Export parts list to .pdf" HorizontalAlignment="Right" Style="{DynamicResource MahApps.Styles.Button.Chromeless}">
<Button.Content>
<iconPacks:PackIconFontAwesome Kind="FilePdfSolid"/>
</Button.Content>
</Button>
</StackPanel>
</controls:TitleControl.TitleContent>
</controls:TitleControl>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Button Margin="0, 5, 5, 5"
Command="{Binding EditButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
Style="{DynamicResource MahApps.Styles.Button.Flat}"
Content="EDIT"/>
</StackPanel>
<DataGrid Grid.Row="1" AutoGenerateColumns="False" Grid.Column="0" Grid.ColumnSpan="2"
ItemsSource="{Binding BillOfMaterials, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}" Margin="5" IsReadOnly="True" SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=ChildItem.PartNumber}" Width="Auto">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconFontAwesome Kind="WrenchSolid" Margin="5" />
<TextBlock Margin="5" Text="PART NUMBER"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=ChildItem.Description}" Width="*">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterialDesign Kind="Description" Margin="5" />
<TextBlock Margin="5" Text="DESCRIPTION"/>
</StackPanel>
</DataGridTextColumn.Header>
<DataGridTextColumn.ElementStyle>
<Style>
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
<Setter Property="TextBlock.TextAlignment" Value="Left"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=ChildItem.Location}" Width="Auto">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterialDesign Kind="LocationOn" Margin="5" />
<TextBlock Margin="5" Text="LOCATION"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=ChildItem.Quantity}" Width="Auto">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Numeric" Margin="5" />
<TextBlock Margin="5" Text="QUANTITY IN STOCK"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Width="Auto" Binding="{Binding Path=Quantity}">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Numeric" Margin="5" />
<TextBlock Margin="5" Text="QUANTITY REQ"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Margin="0" Style="{DynamicResource MahApps.Styles.Button.Flat}"
CommandParameter="{Binding }"
Command="{Binding ViewButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" Content="VIEW"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconTypicons Margin="5" Kind="Eye"/>
<TextBlock Text="VIEW" Margin="5"/>
</StackPanel>
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
BillOfMaterials.cs控制
public partial class BillOfMaterialsControl : UserControl
{
public BillOfMaterialsControl()
{
InitializeComponent();
}
public string Badge
{
get { return (string)this.GetValue(BadgeProperty); }
set { SetValue(BadgeProperty, value); }
}
public static readonly DependencyProperty BadgeProperty = DependencyProperty.Register(
"Badge", typeof(string), typeof(BillOfMaterialsControl), new PropertyMetadata(string.Empty));
public ICommand ViewButtonCommand
{
get { return (ICommand)GetValue(ViewButtonCommandProperty); }
set { SetValue(ViewButtonCommandProperty, value); }
}
public static readonly DependencyProperty ViewButtonCommandProperty = DependencyProperty.Register(
"ViewButtonCommand", typeof(ICommand), typeof(BillOfMaterialsControl), new UIPropertyMetadata(null));
public ICommand ExportButtonCommand
{
get { return (ICommand)GetValue(ExoportButtonCommandProperty); }
set { SetValue(ExoportButtonCommandProperty, value); }
}
public static readonly DependencyProperty ExoportButtonCommandProperty = DependencyProperty.Register(
"ExportButtonCommand", typeof(ICommand), typeof(BillOfMaterialsControl), new UIPropertyMetadata(null));
public ICommand EditButtonCommand
{
get { return (ICommand)GetValue(EditButtonCommandProperty); }
set { SetValue(EditButtonCommandProperty, value); }
}
public static readonly DependencyProperty EditButtonCommandProperty = DependencyProperty.Register(
"EditButtonCommand", typeof(ICommand), typeof(BillOfMaterialsControl), new UIPropertyMetadata(null));
public List<BillOfMaterial> BillOfMaterials
{
get { return (List<BillOfMaterial>)this.GetValue(BillOfMaterialsProperty); }
set { SetValue(BillOfMaterialsProperty, value); }
}
public static readonly DependencyProperty BillOfMaterialsProperty = DependencyProperty.Register(
"BillOfMaterials", typeof(List<BillOfMaterial>), typeof(BillOfMaterialsControl), new PropertyMetadata(null));
}
TitleControl.xaml控制
<UserControl x:Class="Bright_Instruments.Controls.TitleControl"
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:Bright_Instruments.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls">
<Grid Background="{DynamicResource MahApps.Brushes.Accent}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
<ContentPresenter Margin="5" Content="{Binding Icon}"
TextBlock.Foreground="{DynamicResource MahApps.Brushes.IdealForeground}" />
<TextBlock
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
FontSize="12" VerticalAlignment="Center"
HorizontalAlignment="Left" Background="Transparent"
Foreground="{DynamicResource MahApps.Brushes.IdealForeground}"
Padding="5"/>
<Controls:Badged BadgePlacementMode="TopRight" Margin="10, 0, 0, 0" Badge="{Binding Badge}">
<Controls:Badged.Style>
<Style TargetType="Controls:Badged">
<Style.Triggers>
<Trigger Property="Badge" Value="">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
</Controls:Badged.Style>
</Controls:Badged>
</StackPanel>
<ContentPresenter Content="{Binding TitleContent, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="0"/>
<Rectangle Height="2" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Bottom" Fill="{DynamicResource MahApps.Brushes.AccentBase}">
</Rectangle>
</Grid>
</UserControl>
TitleControl.cs控制
public partial class TitleControl : UserControl
{
public TitleControl()
{
InitializeComponent();
}
public string Text
{
get { return (string)this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(TitleControl), new PropertyMetadata(string.Empty));
public string Badge
{
get { return (string)this.GetValue(BadgeProperty); }
set { this.SetValue(BadgeProperty, value); }
}
public static readonly DependencyProperty BadgeProperty = DependencyProperty.Register(
"Badge", typeof(string), typeof(TitleControl), new PropertyMetadata(string.Empty));
public PackIconBase Icon
{
get { return (PackIconBase)this.GetValue(IconProperty); }
set { this.SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon", typeof(PackIconBase), typeof(TitleControl), new PropertyMetadata(null));
public object TitleContent
{
get { return (object)GetValue(TitleContentProperty); }
set { SetValue(TitleContentProperty, value); }
}
public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(
"TitleContent", typeof(object), typeof(TitleControl), new UIPropertyMetadata(null));
}
我在其中托管物料清单控件的视图
<controls:BillOfMaterialsControl
EditButtonCommand="{Binding EditPartsListCommand}"
Badge="{Binding PartsListCount}"
ViewButtonCommand="{Binding ViewPartsListItemCommand}"
ExportButtonCommand="{Binding ExportPartsListToCsvCommand, UpdateSourceTrigger=PropertyChanged}"
BillOfMaterials="{Binding BillOfMaterials, UpdateSourceTrigger=PropertyChanged}"/>
视图视图模型
public ICommand ExportPartsListToCsvCommand => new AsyncRelayCommand(ExportPartsListToCsv);
public async Task ExportPartsListToCsv()
{
var saveFileDialog = new SaveFileDialog();
var filter = $"CSV (*.csv) | *.csv";
saveFileDialog.Filter = filter;
saveFileDialog.DefaultExt = ".csv";
saveFileDialog.FileName = "Inventory.csv";
if (saveFileDialog.ShowDialog() == true)
{
try
{
await CsvService.Write<BillOfMaterial>(saveFileDialog.FileName, BillOfMaterials);
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
}
}
}
BillOfMaterialsControl
使用 TitleControl
控件,该控件又包含 Button
绑定 ExportButtonCommand
(这是 [=14 中的 属性 =]) 作为命令。在这里,您使用了一个相对源绑定,其祖先类型为 UserControl
。
Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}"
画出与此类似的可视化树(仅包含基本部分)。
BillOfMaterialsControl
TitleControl
Button
相对源绑定将向上搜索可视化树以查找 UserControl
类型的控件。您的两个控件都派生自 UserControl
,找到的第一个控件是 TitleControl
,但此控件不包含名为 ExportButtonCommand
的 属性,这就是您得到的绑定失败.
System.Windows.Data Error: 40 : BindingExpression path error: 'ExportButtonCommand' property not found on 'object' ''TitleControl' (Name='')'. BindingExpression:Path=ExportButtonCommand; DataItem='TitleControl' (Name=''); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')
您可以通过以下方式之一解决此问题。
修改绑定以使用控件的具体类型 BillOfMaterialsControl
作为祖先类型。这样TitleControl
不匹配
Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=local:BillOfMaterialsControl}, UpdateSourceTrigger=PropertyChanged}"
指定一个合适的AncestorLevel
在搜索过程中跳过控件。
Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=2}, UpdateSourceTrigger=PropertyChanged}"
2
的值应该可以工作(如果不行,请调整它)。来自 AncestorLevel
上的 documentation:
Gets or sets the level of ancestor to look for, in FindAncestor mode. Use 1 to indicate the one nearest to the binding target element.
嗨,我知道这是很多代码,但我希望有人能帮助我或指出正确的方向,即使在命令和任务上使用断点,我的导出到 csv 命令也没有触发,所以我假设它在某处的数据上下文中找不到,其他一切都有效,数据被填充,编辑按钮有效。
所以我有 2 UserControl
s TitleControl
和 BillOfMaterialsControl
,我在标题控件中托管了一些按钮,而这是在材料清单控件中托管的,看来我的按钮无法使用正在托管在另一个控件中。
我在输出中收到此错误 window:
System.Windows.Data Error: 40 : BindingExpression path error: 'ExportButtonCommand' property not found on 'object' ''TitleControl' (Name='')'. BindingExpression:Path=ExportButtonCommand; DataItem='TitleControl' (Name=''); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')
非常感谢任何帮助。
BillOfMaterials.xaml控制
<UserControl x:Class="Bright_Instruments.Controls.BillOfMaterialsControl"
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:Bright_Instruments.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" xmlns:controls="clr-namespace:Bright_Instruments.Controls"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<controls:TitleControl Grid.Column="0" Badge="{Binding Badge, RelativeSource={RelativeSource AncestorType=UserControl}}" Grid.Row="0" Margin="5" Text="PARTS LIST" Icon="{iconPacks:PicolIcons Kind=ListNumbered}">
<controls:TitleControl.TitleContent>
<StackPanel Margin="0" HorizontalAlignment="Right" Orientation="Horizontal">
<Button ToolTip="Print parts list" Margin="5" HorizontalAlignment="Right" Style="{DynamicResource MahApps.Styles.Button.Chromeless}">
<Button.Content>
<iconPacks:PackIconEntypo Kind="Print"/>
</Button.Content>
</Button>
<Button Margin="5"
Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}" ToolTip="Export parts list to .csv" HorizontalAlignment="Right" Style="{DynamicResource MahApps.Styles.Button.Chromeless}">
<Button.Content>
<iconPacks:PackIconFontAwesome Kind="FileCsvSolid"/>
</Button.Content>
</Button>
<Button Margin="5" ToolTip="Export parts list to .pdf" HorizontalAlignment="Right" Style="{DynamicResource MahApps.Styles.Button.Chromeless}">
<Button.Content>
<iconPacks:PackIconFontAwesome Kind="FilePdfSolid"/>
</Button.Content>
</Button>
</StackPanel>
</controls:TitleControl.TitleContent>
</controls:TitleControl>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<Button Margin="0, 5, 5, 5"
Command="{Binding EditButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
Style="{DynamicResource MahApps.Styles.Button.Flat}"
Content="EDIT"/>
</StackPanel>
<DataGrid Grid.Row="1" AutoGenerateColumns="False" Grid.Column="0" Grid.ColumnSpan="2"
ItemsSource="{Binding BillOfMaterials, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}" Margin="5" IsReadOnly="True" SelectionMode="Single">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=ChildItem.PartNumber}" Width="Auto">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconFontAwesome Kind="WrenchSolid" Margin="5" />
<TextBlock Margin="5" Text="PART NUMBER"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=ChildItem.Description}" Width="*">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterialDesign Kind="Description" Margin="5" />
<TextBlock Margin="5" Text="DESCRIPTION"/>
</StackPanel>
</DataGridTextColumn.Header>
<DataGridTextColumn.ElementStyle>
<Style>
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
<Setter Property="TextBlock.TextAlignment" Value="Left"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=ChildItem.Location}" Width="Auto">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterialDesign Kind="LocationOn" Margin="5" />
<TextBlock Margin="5" Text="LOCATION"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Binding="{Binding Path=ChildItem.Quantity}" Width="Auto">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Numeric" Margin="5" />
<TextBlock Margin="5" Text="QUANTITY IN STOCK"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Width="Auto" Binding="{Binding Path=Quantity}">
<DataGridTextColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconMaterial Kind="Numeric" Margin="5" />
<TextBlock Margin="5" Text="QUANTITY REQ"/>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTemplateColumn Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Margin="0" Style="{DynamicResource MahApps.Styles.Button.Flat}"
CommandParameter="{Binding }"
Command="{Binding ViewButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}}" Content="VIEW"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.Header>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconTypicons Margin="5" Kind="Eye"/>
<TextBlock Text="VIEW" Margin="5"/>
</StackPanel>
</DataGridTemplateColumn.Header>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
BillOfMaterials.cs控制
public partial class BillOfMaterialsControl : UserControl
{
public BillOfMaterialsControl()
{
InitializeComponent();
}
public string Badge
{
get { return (string)this.GetValue(BadgeProperty); }
set { SetValue(BadgeProperty, value); }
}
public static readonly DependencyProperty BadgeProperty = DependencyProperty.Register(
"Badge", typeof(string), typeof(BillOfMaterialsControl), new PropertyMetadata(string.Empty));
public ICommand ViewButtonCommand
{
get { return (ICommand)GetValue(ViewButtonCommandProperty); }
set { SetValue(ViewButtonCommandProperty, value); }
}
public static readonly DependencyProperty ViewButtonCommandProperty = DependencyProperty.Register(
"ViewButtonCommand", typeof(ICommand), typeof(BillOfMaterialsControl), new UIPropertyMetadata(null));
public ICommand ExportButtonCommand
{
get { return (ICommand)GetValue(ExoportButtonCommandProperty); }
set { SetValue(ExoportButtonCommandProperty, value); }
}
public static readonly DependencyProperty ExoportButtonCommandProperty = DependencyProperty.Register(
"ExportButtonCommand", typeof(ICommand), typeof(BillOfMaterialsControl), new UIPropertyMetadata(null));
public ICommand EditButtonCommand
{
get { return (ICommand)GetValue(EditButtonCommandProperty); }
set { SetValue(EditButtonCommandProperty, value); }
}
public static readonly DependencyProperty EditButtonCommandProperty = DependencyProperty.Register(
"EditButtonCommand", typeof(ICommand), typeof(BillOfMaterialsControl), new UIPropertyMetadata(null));
public List<BillOfMaterial> BillOfMaterials
{
get { return (List<BillOfMaterial>)this.GetValue(BillOfMaterialsProperty); }
set { SetValue(BillOfMaterialsProperty, value); }
}
public static readonly DependencyProperty BillOfMaterialsProperty = DependencyProperty.Register(
"BillOfMaterials", typeof(List<BillOfMaterial>), typeof(BillOfMaterialsControl), new PropertyMetadata(null));
}
TitleControl.xaml控制
<UserControl x:Class="Bright_Instruments.Controls.TitleControl"
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:Bright_Instruments.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
xmlns:Controls="http://metro.mahapps.com/winfx/xaml/controls">
<Grid Background="{DynamicResource MahApps.Brushes.Accent}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
<ContentPresenter Margin="5" Content="{Binding Icon}"
TextBlock.Foreground="{DynamicResource MahApps.Brushes.IdealForeground}" />
<TextBlock
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}"
FontSize="12" VerticalAlignment="Center"
HorizontalAlignment="Left" Background="Transparent"
Foreground="{DynamicResource MahApps.Brushes.IdealForeground}"
Padding="5"/>
<Controls:Badged BadgePlacementMode="TopRight" Margin="10, 0, 0, 0" Badge="{Binding Badge}">
<Controls:Badged.Style>
<Style TargetType="Controls:Badged">
<Style.Triggers>
<Trigger Property="Badge" Value="">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
</Controls:Badged.Style>
</Controls:Badged>
</StackPanel>
<ContentPresenter Content="{Binding TitleContent, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="0"/>
<Rectangle Height="2" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Bottom" Fill="{DynamicResource MahApps.Brushes.AccentBase}">
</Rectangle>
</Grid>
</UserControl>
TitleControl.cs控制
public partial class TitleControl : UserControl
{
public TitleControl()
{
InitializeComponent();
}
public string Text
{
get { return (string)this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(TitleControl), new PropertyMetadata(string.Empty));
public string Badge
{
get { return (string)this.GetValue(BadgeProperty); }
set { this.SetValue(BadgeProperty, value); }
}
public static readonly DependencyProperty BadgeProperty = DependencyProperty.Register(
"Badge", typeof(string), typeof(TitleControl), new PropertyMetadata(string.Empty));
public PackIconBase Icon
{
get { return (PackIconBase)this.GetValue(IconProperty); }
set { this.SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon", typeof(PackIconBase), typeof(TitleControl), new PropertyMetadata(null));
public object TitleContent
{
get { return (object)GetValue(TitleContentProperty); }
set { SetValue(TitleContentProperty, value); }
}
public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(
"TitleContent", typeof(object), typeof(TitleControl), new UIPropertyMetadata(null));
}
我在其中托管物料清单控件的视图
<controls:BillOfMaterialsControl
EditButtonCommand="{Binding EditPartsListCommand}"
Badge="{Binding PartsListCount}"
ViewButtonCommand="{Binding ViewPartsListItemCommand}"
ExportButtonCommand="{Binding ExportPartsListToCsvCommand, UpdateSourceTrigger=PropertyChanged}"
BillOfMaterials="{Binding BillOfMaterials, UpdateSourceTrigger=PropertyChanged}"/>
视图视图模型
public ICommand ExportPartsListToCsvCommand => new AsyncRelayCommand(ExportPartsListToCsv);
public async Task ExportPartsListToCsv()
{
var saveFileDialog = new SaveFileDialog();
var filter = $"CSV (*.csv) | *.csv";
saveFileDialog.Filter = filter;
saveFileDialog.DefaultExt = ".csv";
saveFileDialog.FileName = "Inventory.csv";
if (saveFileDialog.ShowDialog() == true)
{
try
{
await CsvService.Write<BillOfMaterial>(saveFileDialog.FileName, BillOfMaterials);
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
}
}
}
BillOfMaterialsControl
使用 TitleControl
控件,该控件又包含 Button
绑定 ExportButtonCommand
(这是 [=14 中的 属性 =]) 作为命令。在这里,您使用了一个相对源绑定,其祖先类型为 UserControl
。
Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl}, UpdateSourceTrigger=PropertyChanged}"
画出与此类似的可视化树(仅包含基本部分)。
BillOfMaterialsControl
TitleControl
Button
相对源绑定将向上搜索可视化树以查找 UserControl
类型的控件。您的两个控件都派生自 UserControl
,找到的第一个控件是 TitleControl
,但此控件不包含名为 ExportButtonCommand
的 属性,这就是您得到的绑定失败.
System.Windows.Data Error: 40 : BindingExpression path error: 'ExportButtonCommand' property not found on 'object' ''TitleControl' (Name='')'. BindingExpression:Path=ExportButtonCommand; DataItem='TitleControl' (Name=''); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')
您可以通过以下方式之一解决此问题。
修改绑定以使用控件的具体类型
BillOfMaterialsControl
作为祖先类型。这样TitleControl
不匹配Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=local:BillOfMaterialsControl}, UpdateSourceTrigger=PropertyChanged}"
指定一个合适的
AncestorLevel
在搜索过程中跳过控件。Command="{Binding ExportButtonCommand, RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=2}, UpdateSourceTrigger=PropertyChanged}"
2
的值应该可以工作(如果不行,请调整它)。来自AncestorLevel
上的 documentation:Gets or sets the level of ancestor to look for, in FindAncestor mode. Use 1 to indicate the one nearest to the binding target element.