添加到另一个 XAML 文件中的画布

问题描述 投票:0回答:1

我正在尝试同时向两个画布添加网格和标签。 从 page.xaml.cs 添加到页面画布有效,但也从 page.xaml.cs 到 cells.xaml 添加到“CellPageSettings”画布不起作用

添加后的计数给我的印象是它有效,但当我到达 cells.xaml 时,没有添加任何内容,计数为 0。

任何指点表示赞赏

下面是 2 个 XAML 文件的设计页面。

页面.XAML

<UserControl xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" 
  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:resx="clr-namespace:test.Languages"
  xmlns:local="clr-namespace:test.ViewModels"
  xmlns:Converters="clr-namespace:test.Converters" 
  xmlns:enums="clr-namespace:test.Enums" 
  x:Class="test.Views.PagesPage"
  x:Name="PagesPageControl" 
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800">

<UserControl.Resources>
    <local:PagesPageViewModel x:Key="xamlViewModel"/>
</UserControl.Resources>

<Grid x:Name="grid" DataContext="{DynamicResource xamlViewModel}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.5*" />
        <ColumnDefinition Width="0.8*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TabControl Background="{x:Null}" Grid.Column="0">
        <TabItem Style="{StaticResource TabItemStyle}" Header="Pages">
            <DockPanel>
                <Canvas x:Name="Pages" Background="LightGray">
                    <!-- Your content for the first area goes here -->
                </Canvas>
<StackPanel VerticalAlignment="Bottom" DockPanel.Dock="Bottom" Orientation="Vertical" HorizontalAlignment="Left" Margin="10">
 <Button x:Name="createNewPage" Style="{StaticResource StandardBtn}" Width="120" Click="createNewPage_Click" Margin="10,0,0,10">
     <TextBlock Text="Create New Page" TextWrapping="Wrap"/>
 </Button>
</StackPanel>
            </DockPanel>
        </TabItem>
    </TabControl>
</Grid>

单元格.XAML

<UserControl xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" 
  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:resx="clr-namespace:test.Languages"
  xmlns:local="clr-namespace:test.ViewModels"
  xmlns:Converters="clr-namespace:test.Converters" 
  xmlns:enums="clr-namespace:test.Enums" 
  x:Class="test.Views.PagesPage"
  mc:Ignorable="d" 
  d:DesignHeight="450" d:DesignWidth="800">

<Grid x:Name="grid" DataContext="{DynamicResource xamlViewModel}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="0.5*" />
        <ColumnDefinition Width="0.8*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TabControl Background="{x:Null}" Grid.Column="0">
        <TabItem Style="{StaticResource TabItemStyle}" Header="CellPages">
        <DockPanel>
         <Canvas x:Name="CellPageSettings" Background="LightGray">
               <!-- Your content for the first area goes here -->
          </Canvas>
           </DockPanel>
        </TabItem>
    </TabControl>
</Grid>

Page.xaml.cs - 添加到两个画布的代码

 public partial class PagesPage : UserControl
 {
    public CellSettingsPage CellSettingsPage { get; private set; }

public PagesPage()
{
  InitializeComponent();
  CellSettingsPage = new CellSettingsPage();
}

    private void createNewPage_Click(object sender, RoutedEventArgs e)
    {
      AddDefaultGridToCanvas();
    }

    private void AddDefaultGridToCanvas()
    {
     numRows = Convert.ToInt32(rowSlider.Value);
     numColumns = Convert.ToInt32(columnSlider.Value);

     //NEEDS tidying up - move to a method - duplicated
     // Create a new DataGrid
     DataGrid newDataGrid = CreateDataGrid(numRows, numColumns);  
     //Creates the grid

     // Create a label for the name
     Label nameLabel = new Label
     {
         Name = currentDateTime,
         Content = "",
         // Set the name as per your requirement
         VerticalAlignment = VerticalAlignment.Bottom,
         HorizontalAlignment = HorizontalAlignment.Left,
         Margin = new Thickness(5, 0, 0, 0) // Adjust margins as needed
     };

     double top = Pages.Children.Count > 0 ? CalculateTotalHeight() : 0; // Adjust the spacing as needed
     double left = 0; //Pages.Children.Count > 0 ? CalculateTotalWidth() : 0; // Adjust as needed

     Canvas.SetTop(newDataGrid, top);
     Canvas.SetLeft(newDataGrid, left);

     double rowHeight = top + numRows * (newDataGrid.RowHeight + 1); // Adjust this based on the actual row height of your DataGrid
     double verticalOffset = Pages.Children.Count > 0 ? rowHeight + 1 : rowHeight; // Adjust the spacing as needed

     Canvas.SetTop(nameLabel, verticalOffset);

     Pages.Children.Add(newDataGrid);
     Pages.Children.Add(nameLabel);

     //Adding to CellSettings Canvas from here - NOT WORKING
     Canvas cellSettingsCanvas = CellSettingsPage.GetCellPageSettingsCanvas();

     DataGrid newDataGridForCellSettings = CreateDataGrid(numRows, numColumns);
     Label nameLabelForCellSettings = new Label
     {
         Name = currentDateTime,
         Content = "",
         VerticalAlignment = VerticalAlignment.Bottom,
         HorizontalAlignment = HorizontalAlignment.Left,
         Margin = new Thickness(5, 0, 0, 0)
     };

     Canvas.SetTop(newDataGridForCellSettings, top);
     Canvas.SetLeft(newDataGridForCellSettings, left);

     double verticalOffsetForCellSettings = cellSettingsCanvas.Children.Count > 0 ? rowHeight + 1 : rowHeight;
     Canvas.SetTop(nameLabelForCellSettings, verticalOffsetForCellSettings);

     cellSettingsCanvas.Children.Add(newDataGridForCellSettings);
     cellSettingsCanvas.Children.Add(nameLabelForCellSettings);
     cellSettingsCanvas.InvalidateVisual();
     cellSettingsCanvas.UpdateLayout();

    int count = cellSettingsCanvas.Children.Count; //shows 2
    Visibility visibility = cellSettingsCanvas.Visibility; // Visible
 }

}

cells.xaml.cs

public partial class CellSettingsPage : UserControl 
{
   
 public Canvas GetCellPageSettingsCanvas()
 {
    return CellPageSettings;
 }
}

CellPageSettings.Children.Count // 显示 0 CellPageSettings.Visibility = 可见

c# wpf xaml canvas datagrid
1个回答
0
投票

请参阅这篇文章,了解有关如何创建单页面应用程序或如何动态加载控件/视图的示例:C# WPF 页面(视图)之间的导航

以下示例假设您遵循提供的链接的模式。以下示例将展示如何为页面设计

UserControl
以及它们如何共享相同的
DataContext
以便显示相同的数据并共享相同的内容部分以共享特定数据视图的相同布局。页面控件名为
MainPage
CellSettingsPage
(我试图尽可能坚持您的原始代码)。

你需要知道

PageId.cs

enum PageId
{
  Default = 0,
  MainPage,
  CellSettingsPage
}

主页.xaml

<UserControl>
  <StackPanel>
    <TextBlock Text="This is the 'MainPage'" />

    <TabControl Background="{x:Null}" Grid.Column="0">
      <TabItem Style="{StaticResource TabItemStyle}" Header="Pages">
    
        <!-- 
             This is the host for the shared view section.
             You can embed it into the page layout by placing this ContentControl
             where you want the TabControl that contains DataGrids to appear.
            
             The ContentControl.Content binds to a property on this UserControl.
             Simply define a DataTemplate e.g. in App.xaml to define the visuals.
             Because the other page will use the DataTemplate (and data model),
             both will show the exact same data view 
             (without duplicating any data as the data is shared).
        -->
        <ContentControl Content="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=SharedDataSource}" />
      </TabItem>
    </TabControl>
  </StackPanel>
</UserControl>

MainPage.xaml.cs

partial class MainPage : UserControl
{
  public object SharedDataSource
  {
    get => (object)GetValue(SharedDataSourceProperty);
    set => SetValue(SharedDataSourceProperty, value);
  }

  public static readonly DependencyProperty SharedDataSourceProperty = DependencyProperty.Register(
    "SharedDataSource",
    typeof(object),
    typeof(MainPage),
    new PropertyMetadata(default));

  public MainPage()
  {
    InitializeComponent();
  }
}

CellSettingsPage.xaml

<UserControl>
  <StackPanel>
    <TextBlock Text="This is the 'CellSettingsPage'" />

    <TabControl Background="{x:Null}" Grid.Column="0">
      <TabItem Style="{StaticResource TabItemStyle}" Header="CellPages">
    
        <!-- 
             This is the host for the shared view section.
             You can embed it into the page layout by placing this ContentControl
             where you want the TabControl that contains DataGrids to appear.
            
             The ContentControl.Content binds to a property on this UserControl.
             Simply define a DataTemplate e.g. in App.xaml to define the visuals.
             Because the other page will use the DataTemplate (and data model),
             both will show the exact same data view 
             (without duplicating any data as the data is shared).
        -->
        <ContentControl Content="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=SharedDataSource}" />
      </TabItem>
    </TabControl>
  </StackPanel>
</UserControl>

CellSettingsPage.xaml.cs

partial class CellSettingsPage : UserControl
{
  public object SharedDataSource
  {
    get => (object)GetValue(SharedDataSourceProperty);
    set => SetValue(SharedDataSourceProperty, value);
  }

  public static readonly DependencyProperty SharedDataSourceProperty = DependencyProperty.Register(
    "SharedDataSource",
    typeof(object),
    typeof(CellSettingsPage),
    new PropertyMetadata(default));

  public CellSettingsPage()
  {
    InitializeComponent();
  }
}

应用程序.xaml

<Application>
  <Application.Resources>

    <!-- The DataTemplate for the MainPageViewModel -->
    <DataTemplate DataType="MainPageViewModel">
      <MainPage SharedDataSource="{Binding SharedData}" />
    </DataTemplate>

    <!-- The DataTemplate for the CellSettingsPageViewModel -->
    <DataTemplate DataType="CellSettingsPageViewModel">
      <MainPage SharedDataSource="{Binding SharedData}" />
    </DataTemplate>

    <!-- 
         The DataTemplate for the SharedDataItem.
         This will actually show the stacked DataGrid elements.
    -->
    <DataTemplate DataType="SharedDataItem">
      <ListBox ItemsSource0"{Binding DataTables}">
        <ListBox.ItemTemplate>
          <DataTemplate DataType="DataTable">
            <DataGrid ItemsSource="{Binding}" />
          </DataTemplate>
        </ListBox.ItemTemplate>
      </ListBox>     
    </DataTemplate>
  </Application.Resources>
</Application>

SharedDataItem.cs

// TODO::Implement INotifyPropertyChanged. 
// If there are properties that change their values 
// then let them raise the INotifyPropertyChanged.PropertyChanged event.
class SharedDataItem : INotifyPropertyChanged
{
  public ObservableCollection<DataTable> DataTables { get; }

  public SharedDataItem()
    => this.DataTables = new ObservableCollection<DataTable>();
}

MainPageViewModel.cs

// TODO::Implement INotifyPropertyChanged. 
// If there are properties that change their values 
// then let them raise the INotifyPropertyChanged.PropertyChanged event.
class MainPageViewModel : INotifyPropertyChanged
{
  public string Title { get; }
  public SharedDataItem ShareData { get; }

  public MainPageViewModel(string title, SharedDataItem sharedDataContext)
  {  
    this.Title = title;
    this.SharedData = sharedDataContext;
  }
}

CellSettingsPageViewModel.cs

// TODO::Implement INotifyPropertyChanged. 
// If there are properties that change their values 
// then let them raise the INotifyPropertyChanged.PropertyChanged event.
class CellSettingsPageViewModel : INotifyPropertyChanged
{
  public string Title { get; }
  public SharedDataItem ShareData { get; }

  public CellSettingsPageViewModel(string title, SharedDataItem sharedDataContext)
  {  
    this.Title = title;
    this.SharedData = sharedDataContext;
  }
}

MainViewModel.cs
该示例使用在Microsoft learn:中继命令逻辑

中找到的 RelayCommand 实现
// TODO::Implement INotifyPropertyChanged. 
// If there are properties that change their values 
// then let them raise the INotifyPropertyChanged.PropertyChanged event.
class MainViewModel : INotifyPropertyChanged
{
  // TODO::Raise INotifyPropertyChanged.PropertyChanged event
  public string CurrentContext { get; set: }

  public ICommand SelectPageContextCommand { get; }
  private Dictionary<PageId, INotifyPropertyChanged> PageContexts { get; } 

  public MainViewModel(string title)
  {
    this.SelectPageContextCommand = new RelayCommand(ExecuteSelectPageContextCommand, CanExecuteSelectPageContextCommand);
    var sharedDataContext = new SharedDataItem();
   
    // Add shared data to the 'sharedDataContext'.
    // TODO::Create the DataTables that will be displayed in a DataGrid each.
    // Conceptual example code:
    for (int datTableCount = 0; dataTableCount < 3; dataTableCount++)
    {
      DataTable sharedDataTable = CreateDataTable();
      sharedDataContext.DataTables.Add(sharedDataTable);
    }
   
    this.PageContexts = new Dictionary<PageId, INotifyPropertyChanged>
    {
      { PageId.MainPage, new MainPageViewModel("Main page", sharedDataContext) },
      { PageId.CellSettingsPage, new CellSettingsPageViewModel("Cell settings page", sharedDataContext) },
    };

    // Set start page
    SelectCurrentContext(PageId.MainPage);
  }
      
  private void SelectCurrentContext(PageId pageContextId)
  {
    if (this.PageContexts.TryGetValue(pageContextId, out INotifyPropertyChanged pageContext))
    {
      this.CurrentContext = pageContext;
    }
  }

  private bool CanExecuteSelectPageContextCommand(object commandParameter)
    => commandParameter is PageId pageId 
      && this.PageContexts.ContainsKey(pageId);

  private void ExecuteSelectPageContextCommand(object commandParameter)
    => SelectCurrentContext((PageId)commandParameter); 
}

MainWindow.xaml

<Window>
  <Window.DataContext>
    <MainViewModel />
  </Window.DataContext>

  <StackPanel>
  
    <!-- Page navigation -->
    <StackPanel Orientation="Horizontal">
      <Button Content="Main page" 
              Command="{Binding SelectPageContextCommand}" 
              CommandParameter="{x:Static PageId.MainPage}" />
      <Button Content="Show Welcome Screen" 
              Command="{Binding SelectPageContextCommand}" 
              CommandParameter="{x:Static PageId.CellSettingsPage}" />
    </StackPanel>
  
    <!-- 
      Host of CurrentContext. 
      Automatically displays the DataTemplate (defined in App.xaml) 
      that matches the current data type (e.g. CellSettingsPageViewModel)
    -->
    <ContentControl Content="{Binding CurrentContext}" />
  <StackPanel>
</Window>

注意:代码是在没有 IDE 的情况下使用 a lot 复制和粘贴在该编辑器中编写的。因此,它可能包含一些与复制和粘贴相关的错误。当您遇到毫无意义的代码(例如错误的变量名称和一般拼写错误等)时,请记住这一点。
但是,如果您满足本示例中的 TODO 代码注释,则该代码应该可以编译并执行。

© www.soinside.com 2019 - 2024. All rights reserved.