天道酬勤,学无止境

Dynamic and Immutable UIElement Arrays

Question

I have a WrapPanel that contains multiple Canvas of the same size. Each Canvas has some UIElements (i.e. TextBox, TextBlock, Buttons etc) as children. The creation of each Canvas (including its UIElement children) and the number of Canvas to be created are all done in run-time code behind (no XAML).

Initially I did the following, which works:

// declare as class properties, so all function can access them
WrapPanel wp = new WrapPanel();
Canvas[] cv = new Canvas[500];
TextBox[] tb = new TextBox[500];

// A function (e.g. a Button_Click event) that generates multiple Canvas in a WrapPanel
for (int i = 0; i<myInt; i++)
{
cv[i] = new Canvas();
tb[i] = new TextBox();
cv[i].Children.Add(tb[i]);
wp.Children.Add(cv[i]);
}

The above code is straight forwards works OK - Until I implement add, minus and destroy buttons where I could

1. Add an additional `Canvas` on a click event
2. Remove the last `Canvas` on a click event
3. Destroy a specific `Canvas` in the `WrapPanel` on a click event (may ba a little cross icon in each `Canvas`)

If I process some combination of the above 3 actions, I could easily create UIElements of the same index or create Canvas that goes out of the range of what it had been declared initially.

I looked into List however, each Canvas have different properties (each also has UIElement Children with different properties) and I can't figure out how List would solve it. A way for me to go around that is to declare a super large Array size for Canvas (e.g. Canvas[] cv = new Canvas[99999] but I though that's not very efficient.

Also, if I use List, how could I change properties of a specific UIElement after the they are generated? E.g. If i add 10 Canvas and add to List, and after they are all generated, I need to select the 5th Canvas and change a TextBox.Text, how do I access it like I did in an Array (i.e. tb[5].Text = "Hello")?

Can anyone show me some approaches to this problem?

Answer1

Just a direct translation on how to do this with a list instead below. Given your code I don't know why you want to keep track of the canvas and textbox'es in a list - you can just access the children collection of the WrapPanel directly instead - let's assume you do need these separate collections for now.

 WrapPanel wp = new WrapPanel();
 List<Canvas> cvList = new List<Canvas>();
 List<TextBox> tbList = new List<TextBox>();

 public void Init()
{

    int myInt = 500;
    // in a function (e.g. a Button_Click event) to generate the multiple Canvas in a WrapPanel
    for (int i = 0; i < myInt; i++)
    {
        Canvas cv = new Canvas();
        TextBox tb = new TextBox();
        cv.Children.Add(tb);
        wp.Children.Add(cv);

        cvList.Add(cv);
        tbList.Add(tb);
    }
}


public void AddCanvas()
{
    Canvas cv = new Canvas();
    TextBox tb = new TextBox();
    cv.Children.Add(tb);
    wp.Children.Add(cv);
    cvList.Add(cv);
    tbList.Add(tb);
}

public void RemoveCanvas()
{
        wp.Children.RemoveAt(wp.Children.Count-1);
        cvList.RemoveAt(cvList.Count - 1);
        tbList.RemoveAt(cvList.Count - 1);
}

Edit for added comment:

E.g. If i add 10 Canvas, and after they are all generated, I need to select the 5th Canvas and change a TextBox.Text, how do I access it like I did in an Array (i.e. tb[5].Text = "Hello")?

You can just access the children directly. You know you only added Canvas elements to your WrapPanel. So you could do (wp is the WrapPanel again):

TextBox textbox = (wp.Children[5] as Canvas).Children[0] as TextBox;
textbox.Text = "Hello";
Answer2

Just operate directly on the WrapPanel's Children collection.

public partial class MainWindow : Window
{        

    public MainWindow()
    {
        InitializeComponent();
        AddCanvasToWrapPanel(this.TestWrapPanel);
        RemoveLastCanvasFromWrapPanel(this.TestWrapPanel);
        AddCanvasToWrapPanel(this.TestWrapPanel);
        DestroyCanvasAtWrapPanelIndex(this.TestWrapPanel, 0);

    }

    private void AddCanvasToWrapPanel(WrapPanel wp)
    {
        TextBox t = new TextBox();
        Canvas c = new Canvas();
        c.Children.Add(t);
        wp.Children.Add(c);
    }

    private void RemoveLastCanvasFromWrapPanel(WrapPanel wp)
    {
        wp.Children.RemoveAt(wp.Children.Count - 1);
    }

    private void DestroyCanvasAtWrapPanelIndex(WrapPanel wp, int index)
    {
        wp.Children.RemoveAt(index);
    }


}
}

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.

相关推荐
  • Regarding immutable List (created by Arrays.asList())
    Question When we create a list from an array using java.util.Arrays.asList(), the list is immutable. I am just curious to know why do we want to create a immutable list when the basic purpose of List (or Set or Map) is to have dynamic size and to be able to add, remove elements at will. When we need a fixed size data structure we go for Array and when we need a dynamic data structure we go for List or Set or Map etc. So what is the purpose of having a immutable list? I came across this while working on my assignment. Answer1 When we create a list from an array using java.util.Arrays.asList()
  • What is the difference between List.of and Arrays.asList?
    Question Java 9 introduced new factory methods for lists, List.of: List<String> strings = List.of("first", "second"); What's the difference between the previous and the new option? That is, what's the difference between this: Arrays.asList(1, 2, 3); and this: List.of(1, 2, 3); Answer1 Arrays.asList returns a mutable list while the list returned by List.of is immutable: List<Integer> list = Arrays.asList(1, 2, null); list.set(1, 10); // OK List<Integer> list = List.of(1, 2, 3); list.set(1, 10); // Fails with UnsupportedOperationException Arrays.asList allows null elements while List.of doesn't
  • How to create a dynamic grid containing panels
    Question I have a requirement to dynamically create a WPF Grid that has 3 columns and the number of rows will depend on the amount of panels I need. The first panel will be in grid location 0,0 the next in 0,1 -> 0,2 -> 1,0 -> 1,1 etc.. So if I needed 20 panels the grid would have 3 cols and 7 rows. And the Grid should fill the whole window And each panel should have a heading and a progress bar on it. I guess I would have my panel as a seperate user control I'm starting out with WPF so any help would be great Thanks a lot Answer1 You'll have to do it in code-behind as far as I know. You'll
  • What is the difference between the string and []byte in Go?
    Question s := "some string" b := []byte(s) // convert string -> []byte s2 := string(b) // convert []byte -> string what is the difference between the string and []byte in Go? When to use "he" or "she"? Why? bb := []byte{'h','e','l','l','o',127} ss := string(bb) fmt.Println(ss) hello The output is just "hello", and lack of 127, sometimes I feel that it's weird. Answer1 string and []byte are different types, but they can be converted to one another: 3 . Converting a slice of bytes to a string type yields a string whose successive bytes are the elements of the slice. 4 . Converting a value of a
  • Parallel Generation of UI
    Question We have a WPF application that has a ListBox with a VirtualizingStackPanel with caching. Not because it has massively many elements (typically less than 20 but perhaps up to 100 or more in extreme cases) but because elements take time to generate. The elements are in fact UIElement objects. So the application dynamically needs to generate UIElements. The problem is that even though the virtualization appears to work, the application is still slow to become responsive, and this is in a proof of concept solution with minimal "noise". So we figured that since the main problem is that we
  • Why no immutable arrays in scala standard library?
    Question Scala has all sorts sorts of immutable sequences like List, Vector,etc. I have been surprised to find no implementation of immutable indexed sequence backed by a simple array (Vector seems way too complicated for my needs). Is there a design reason for this? I could not find a good explanation on the mailing list. Do you have a recommendation for an immutable indexed sequence that has close to the same performances as an array? I am considering scalaz's ImmutableArray, but it has some issues with scala trunk for example. Thank you Answer1 You could cast your array into a sequence. val
  • Are immutable arrays possible in .NET?
    Question Is it possible to somehow mark a System.Array as immutable. When put behind a public-get/private-set they can't be added to, since it requires re-allocation and re-assignment, but a consumer can still set any subscript they wish: public class Immy { public string[] { get; private set; } } I thought the readonly keyword might do the trick, but no such luck. Answer1 ReadOnlyCollection<T> is probably what you are looking for. It doesn't have an Add() method. Answer2 The Framework Design Guidelines suggest returning a copy of the Array. That way, consumers can't change items from the
  • 2021-04-11
    Section 9 three modifiers abstract (abstract class, abstract method) 1. Abstraction in life: searching for animals is all sub-objects of animals, but there are no specific objects of animals. 2. Objects that are not created: The program simulates the real world and solves real problems. In reality, all objects are subclasses of animals, and there are no animal objects. Therefore, Animal should not be independently created as an object. 3. Abstract class: A class modified by abstract is called an abstract class. An abstract class means an incomplete class or a class that is not concrete enough
  • Are String Arrays mutable?
    Question I wonder if String arrays in Java are mutable ? I know that Strings are immutable, but how about string Arrays ? If I have a string array, and change the content, will a new string object be created ? Or will the actual value just be changed ? Thanks in advance Answer1 The Strings contained in the String[] are indeed immutable, but the array is mutable. This is well explained in this answer: Immutability means that objects of a certain type can not change in any meaningful way to outside observers Integer, String, etc are immutable Generally all value types should be Array objects are
  • How do you create an immutable array in Swift?
    Question How do I create an immutable array in Swift? A superficial reading of the docs would suggest you can just do let myArray = [1,2,3] But sadly this actually produces a mutable, fixed-size array. This mutability creates the usual puzzles with unsuspected aliasing and functions mutating their arguments: let outterArray = [myArray, myArray] outterArray[0][0] = 2000 outterArray //=> [[2000,2,3],[2000,2,3]] surprise! func notReallyPure(arr:Int[]) -> () { arr[0] = 3000 } notReallyPure(myArray) myArray // => [3000,2,3] Not much better than C. If I want immutability, is the best option really
  • Python: what is the difference between (1,2,3) and [1,2,3], and when should I use each?
    Question In many places, (1,2,3) (a tuple) and [1,2,3] (a list) can be used interchangeably. When should I use one or the other, and why? Answer1 From the Python FAQ: Lists and tuples, while similar in many respects, are generally used in fundamentally different ways. Tuples can be thought of as being similar to Pascal records or C structs; they're small collections of related data which may be of different types which are operated on as a group. For example, a Cartesian coordinate is appropriately represented as a tuple of two or three numbers. Lists, on the other hand, are more like arrays
  • Understanding deeply spliterator characteristics
    Question In order to try to deeply understand java streams and spliterators, I have some subtle questions about spliterator characteristics: Q1: Stream.empty() vs Stream.of() (Stream.of() without args) Stream.empty(): SUBSIZED, SIZED Stream.of(): SUBSIZED, IMMUTABLE, SIZED, ORDERED Why Stream.empty() doesn't have the same characteristics of Stream.of()? Note that it has impacts when using in conjunction with Stream.concat() (specially not having ORDERED). I would say that Stream.empty() should have not just IMMUTABLE and ORDERED but also DISTINCT and NONNULL. Also it make sense Stream.of()
  • Leetcode data structure & algorithm: array and string
    1. Introduction Array will not be introduced, one-dimensional, two-dimensional, dynamic, etc., the most basic data structure. Note that when using strings, the situation is different in different languages. The array and string are simply recorded. (1) Comparison function Strings have its own比较函数. Can we use "==" to compare two strings? It depends on the answer to the following question: Does the language we use support运算符重载? If the answer is yes (for example, C++). We可以使用"==" to compare two strings. If the answer is no (for example, Java), we可能无法使用"==" to compare two strings. When we use "=="
  • How to find a control with a specific name in an XAML UI with C# code?
    Question I have dynamic added controls in my XAML UI. How I can find a specific control with a name. Answer1 There is a way to do that. You can use the VisualTreeHelper to walk through all the objects on the screen. A convenient method I use (obtained it somewhere from the web) is the FindControl method: public static T FindControl<T>(UIElement parent, Type targetType, string ControlName) where T : FrameworkElement { if (parent == null) return null; if (parent.GetType() == targetType && ((T)parent).Name == ControlName) { return (T)parent; } T result = null; int count = VisualTreeHelper
  • Is it possible to bind a Canvas's Children property in XAML?
    Question I'm a little surprised that it is not possible to set up a binding for Canvas.Children through XAML. I've had to resort to a code-behind approach that looks something like this: private void UserControl_Loaded(object sender, RoutedEventArgs e) { DesignerViewModel dvm = this.DataContext as DesignerViewModel; dvm.Document.Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Items_CollectionChanged); foreach (UIElement element in dvm.Document.Items) designerCanvas.Children.Add(element); } private void Items_CollectionChanged(object sender
  • Pass array from node-postgres to plpgsql function
    Question The plpgsql function: CREATE OR REPLACE FUNCTION testarray (int[]) returns int as $$ DECLARE len int; BEGIN len := array_upper($1); return len; END $$ language plpgsql; The node-postgres query + test array: var ta = [1,2,3,4,5]; client.query('SELECT testarray($1)', [ta], function(err, result) { console.log('err: ' + err); console.log('result: ' + result); }); Output from node server: err: error: array value must start with "{" or dimension information result: undefined I also tried cast the parameter in the client query like testarray($1::int[]) which returned the same error. I
  • Java array learning
    mind Mapping Guidance Array, such a concept, we have also learned in the previous programming learning. Array is one of the most commonly used data types in programming languages. Multiple data can be stored. An array is essentially a collection of numbers. For example, if we want to save 30 similar data, if we don't use an array, then we need to set 30 variables to save. With an array, we only need to set a variable.Array is a reference data type composed of data of the same type in sequence Array specification The stored data is the same data typeThe length of the array is determined when it
  • Hosting ViewModels in ContentControl in WPF
    Question I have a traditional form layout with a menu bar at the top and status bar at the bottom. When the user selects a menu item, the space in-between (the form's entire remaining client area) gets replaced with a user control - think of an SDI app that can host multiple types of documents. If you know of a better way to go about this, please chime in. For now, I'm trying to get it to work in a very simplified version with a ContentControl, but I cannot get it to update the screen when its DataContext is set. Here's the very simple code for ViewModelA. ViewModelB is identical, except for
  • enum vs immutable in D
    Question What's the difference between enum i = 2; enum s = "Hello"; and immutable i = 2; immutable s = "Hello"; in D 2.0? Answer1 An enum is a user-defined type, not a variable. enum e = 2; is a short-hand for something like this enum : int { e = 2 } (i.e. an anonymous enum with one member e), see the documentation. By definition, all members of an anonymous enum are placed into the current scope. So, e is a type member placed into the current scope, where it behaves like a literal. immutable i = 2; on the other hand actually creates a variable i of type int. This difference has a couple of
  • Analysis on the realization of python list
    Knowing the reason must also be aware of the reason. There are really not many container objects in python. Usually we will use the corresponding container according to the needs with list . Use list variable length data, want to reuse set , want to quickly match with dict , Character processing uses str , but why can this effect be achieved? For example, when we use list , we know that this thing can store various formats at will, such as integers, floating points, strings, and even other containers such as nested list . Is the underlying principle implemented using arrays or using Linked