访问动态创建的面板上的动态创建的控件

问题描述

我正在创建这个面板

@available(iOS 15.0,*)
struct CustomSheet: View {
    @State private var isPresented = false
    
    var body: some View {
        Button(isPresented ? "dismiss content" : "present content",action: {
            isPresented.toggle()
        })
        CustomSheet_UI(isPresented: $isPresented,detents: [.medium()],smallestUndimmedDetentIdentifier: .large){
            Rectangle()
                .frame(maxWidth: .infinity,maxHeight: .infinity,alignment: .center)
                .foregroundColor(.clear)
                .border(Color.blue,width: 3)
                .overlay(Text("Hello,World!"))
        }
    }
}

@available(iOS 15.0,*)
struct CustomSheet_UI<Content: View>: UIViewControllerRepresentable {
    
    let content: Content
    @Binding var isPresented: Bool
    let detents : [UISheetPresentationController.Detent]
    let smallestUndimmedDetentIdentifier: UISheetPresentationController.Detent.Identifier?
    let prefeRSScrollingExpandsWhenScrolledToEdge: Bool
    let prefersEdgeAttachedInCompactHeight: Bool
    
    init(isPresented: Binding<Bool>,detents : [UISheetPresentationController.Detent] = [.medium(),.large()],smallestUndimmedDetentIdentifier: UISheetPresentationController.Detent.Identifier? = .medium,prefeRSScrollingExpandsWhenScrolledToEdge: Bool = false,prefersEdgeAttachedInCompactHeight: Bool = true,@viewbuilder content: @escaping () -> Content) {
        self.content = content()
        self.detents = detents
        self.smallestUndimmedDetentIdentifier = smallestUndimmedDetentIdentifier
        self.prefersEdgeAttachedInCompactHeight = prefersEdgeAttachedInCompactHeight
        self.prefeRSScrollingExpandsWhenScrolledToEdge = prefeRSScrollingExpandsWhenScrolledToEdge
        self._isPresented = isPresented
    }
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    func makeUIViewController(context: Context) -> CustomSheetViewController<Content> {
        let vc = CustomSheetViewController(coordinator: context.coordinator,detents : detents,smallestUndimmedDetentIdentifier: smallestUndimmedDetentIdentifier,prefeRSScrollingExpandsWhenScrolledToEdge:  prefeRSScrollingExpandsWhenScrolledToEdge,prefersEdgeAttachedInCompactHeight: prefersEdgeAttachedInCompactHeight,content: {content})
        return vc
    }
    
    func updateUIViewController(_ uiViewController: CustomSheetViewController<Content>,context: Context) {
        if isPresented{
            uiViewController.presentModalView()
        }else{
            uiViewController.dismissModalView()
        }
    }
    class Coordinator: NSObject,UIAdaptivePresentationControllerDelegate {
        var parent: CustomSheet_UI
        init(_ parent: CustomSheet_UI) {
            self.parent = parent
        }
        //Adjust the variable when the user dismisses with a swipe
        func presentationControllerDiddismiss(_ presentationController: UIPresentationController) {
            if parent.isPresented{
                parent.isPresented = false
            }
            
        }
        
    }
}

@available(iOS 15.0,*)
class CustomSheetViewController<Content: View>: UIViewController {
    let content: Content
    let coordinator: CustomSheet_UI<Content>.Coordinator
    let detents : [UISheetPresentationController.Detent]
    let smallestUndimmedDetentIdentifier: UISheetPresentationController.Detent.Identifier?
    let prefeRSScrollingExpandsWhenScrolledToEdge: Bool
    let prefersEdgeAttachedInCompactHeight: Bool
    
    init(coordinator: CustomSheet_UI<Content>.Coordinator,@viewbuilder content: @escaping () -> Content) {
        self.content = content()
        self.coordinator = coordinator
        self.detents = detents
        self.smallestUndimmedDetentIdentifier = smallestUndimmedDetentIdentifier
        self.prefersEdgeAttachedInCompactHeight = prefersEdgeAttachedInCompactHeight
        self.prefeRSScrollingExpandsWhenScrolledToEdge = prefeRSScrollingExpandsWhenScrolledToEdge
        super.init(nibName: nil,bundle: .main)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    func dismissModalView(){
        dismiss(animated: true,completion: nil)
    }
    func presentModalView(){
        
        let hostingController = UIHostingController(rootView: content)
        
        hostingController.modalPresentationStyle = .popover
        hostingController.presentationController?.delegate = coordinator as UIAdaptivePresentationControllerDelegate
        if let hostPopover = hostingController.popoverPresentationController {
            hostPopover.sourceView = super.view
            let sheet = hostPopover.adaptiveSheetPresentationController
            sheet.detents = detents
            sheet.smallestUndimmedDetentIdentifier =
            smallestUndimmedDetentIdentifier
            sheet.prefeRSScrollingExpandsWhenScrolledToEdge =
            prefeRSScrollingExpandsWhenScrolledToEdge
            sheet.prefersEdgeAttachedInCompactHeight =
            prefersEdgeAttachedInCompactHeight
            sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
            
        }
        if presentedViewController == nil{
            present(hostingController,animated: true,completion: nil)
        }
    }
}

创建面板后如何访问面板上的控件。这些面板不止一个,它们可以随时移除和重新绘制,因此需要动态创建。

我尝试过这样的事情,但我认为我离得很远。 p 是相关的面板编号。

Label PrinterName = new Label();
                Label Format = new Label();
                Label Count = new Label();
                Label FormatLabel = new Label();
                Label PrintedLabel = new Label();
                Label ResourceLabel = new Label();
                Button Detailsbutton = new Button();
                Button PrintButton = new Button();
                PictureBox LabelImageBox = new PictureBox();
                Panel panel1 = new Panel();
                ComboBox PrinterComboBox = new ComboBox();
                PrinterName.Font = new System.Drawing.Font("Microsoft Sans Serif",16F,System.Drawing.FontStyle.Regular,system.drawing.graphicsUnit.Point,((byte)(0)));
                PrinterName.Location = new System.Drawing.Point(11,9);
                PrinterName.Name = "PrinterName";
                PrinterName.Size = new System.Drawing.Size(169,28);
                PrinterName.TabIndex = 5;
                PrinterName.Text = printers[pc * 3];
                // 
                // Format
                // 
                Format.Font = new System.Drawing.Font("Microsoft Sans Serif",((byte)(0)));
                Format.Location = new System.Drawing.Point(195,51);
                Format.Name = "Format" +pc.ToString();
                Format.Size = new System.Drawing.Size(169,28);
                Format.TabIndex = 7;
                Format.Text = "Label Format";
                Count.Font = new System.Drawing.Font("Microsoft Sans Serif",((byte)(0)));
                Count.Location = new System.Drawing.Point(370,51);
                Count.Name = "Count";
                Count.Size = new System.Drawing.Size(109,28);
                Count.TabIndex = 8;
                Count.Text = "Count";
                // 
                // Detailsbutton
                // 
                Detailsbutton.Location = new System.Drawing.Point(485,60);
                Detailsbutton.Name = "Detailsbutton";
                Detailsbutton.Size = new System.Drawing.Size(91,45);
                Detailsbutton.TabIndex = 11;
                Detailsbutton.Text = "Datails";
                Detailsbutton.UseVisualStyleBackColor = true;
                // 
                // PrinterComboBox
                // 
                PrinterComboBox.Font = new System.Drawing.Font("Microsoft Sans Serif",((byte)(0)));
                PrinterComboBox.FormattingEnabled = true;
                PrinterComboBox.Location = new System.Drawing.Point(16,66);
                PrinterComboBox.Name = "PrinterComboBox";
                PrinterComboBox.Size = new System.Drawing.Size(157,33);
                PrinterComboBox.TabIndex = 10;
                PrinterComboBox.Items.AddRange(resourcenumbers());
                PrinterComboBox.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
                PrinterComboBox.AutoCompleteSource = AutoCompleteSource.ListItems;
                PrinterComboBox.SelectedindexChanged += (s,e) => { selectedindexchanged(pc); };
                // 
                // PrintButton
                // 
                PrintButton.Location = new System.Drawing.Point(485,9);
                PrintButton.Name = "PrintButton";
                PrintButton.Size = new System.Drawing.Size(91,45);
                PrintButton.TabIndex = 9;
                PrintButton.Text = "Print";
                PrintButton.UseVisualStyleBackColor = true;
                // 
                // FormatLabel
                // 
                FormatLabel.Font = new System.Drawing.Font("Microsoft Sans Serif",((byte)(0)));
                FormatLabel.Location = new System.Drawing.Point(195,23);
                FormatLabel.Name = "FormatLabel";
                FormatLabel.Size = new System.Drawing.Size(169,28);
                FormatLabel.TabIndex = 12;
                FormatLabel.Text = "Format:";
                // 
                // PrintedLabel
                // 
                PrintedLabel.Font = new System.Drawing.Font("Microsoft Sans Serif",((byte)(0)));
                PrintedLabel.Location = new System.Drawing.Point(370,23);
                PrintedLabel.Name = "PrintedLabel";
                PrintedLabel.Size = new System.Drawing.Size(109,28);
                PrintedLabel.TabIndex = 13;
                PrintedLabel.Text = "Printed:";
                // 
                // ResourceLabel
                // 
                ResourceLabel.Font = new System.Drawing.Font("Microsoft Sans Serif",((byte)(0)));
                ResourceLabel.Location = new System.Drawing.Point(20,37);
                ResourceLabel.Name = "ResourceLabel";
                ResourceLabel.Size = new System.Drawing.Size(169,28);
                ResourceLabel.TabIndex = 14;
                ResourceLabel.Text = "Resoruce:";
                // 
                // LabelImageBox
                // 
                LabelImageBox.Location = new System.Drawing.Point(589,8);
                LabelImageBox.Name = "LabelImageBox" + pc.ToString();
                LabelImageBox.Size = new System.Drawing.Size(206,107);
                LabelImageBox.TabIndex = 15;
                LabelImageBox.TabStop = false;
                // 
                // panel1
                // 
                panel1.BackColor = System.Drawing.SystemColors.ActiveBorder;
                panel1.Controls.Add(LabelImageBox);
                panel1.Controls.Add(ResourceLabel);
                panel1.Controls.Add(PrintedLabel);
                panel1.Controls.Add(FormatLabel);
                panel1.Controls.Add(Detailsbutton);
                panel1.Controls.Add(PrinterComboBox);
                panel1.Controls.Add(PrintButton);
                panel1.Controls.Add(Format);
                panel1.Controls.Add(Count);
                panel1.Controls.Add(PrinterName);
                panel1.Location = new System.Drawing.Point(106,91 + 150*pc);
                panel1.Name = "panel" + pc.ToString();
                panel1.Size = new System.Drawing.Size(815,126);
                panel1.TabIndex = 9;
                this.Controls.Add(panel1);

我还需要能够访问诸如组合框的选定索引之类的内容,例如

this.Controls["panel" + p.ToString()].Controls["Format" + p.ToString()].Text = "the thing";

解决方法

您需要为每个子控件添加一个标识符或一些东西来引用该控件。 您可以使用名称、设置标签等。

下面是删除面板中动态创建的特定按钮的示例。

foreach (Control p in this.Controls)
If (p is Panel)
{ 
    foreach (Control PanelControl in p.Controls)
    If (PanelControl.Tag.Contains("RemoveThisButton"))
    { 
        PanelControl.Dispose();
    }
}

修改数组时要小心,因为这会破坏循环。