问:
C#: Docking label at middle bottom of panel and have it grow with content on run time.
I need a label to appear in the middle bottom (like 30px above the bottom line) of a panel, that also auto sizes to wrap the text depending on how long the text is.

So far I can only have the label auto size to wrap the text and have it docked at the bottom. But it is at bottom left and not middle.
As is on this example Long Text Image and Image of short text I'd like to center
(sorry the text is not clear but its at the bottom in white)

I was able to achieve the auto size using the ClientSizeChanged event as below.

```<code>private void Panel1_ClientSizeChanged(object sender, EventArgs e)
    {
        label8.MaximumSize = new Size((sender as Control).ClientSize.Width - label8.Left, 10000);
    }
</code>```

How do I have the text at the middle? It should be able to maintain the bottom middle (dock) position as I resize the panel.

答:
Try following:

To your panel add TableLayoutPanel with following Properties:

```<code>tableLayoutPanel1.AutoSize = true; // This can be set at the end if you use designer
tableLayoutPanel1.ColumnCount = 1;
tableLayoutPanel1.RowCount = 1;
tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom;
panel1.Controls.Add(tableLayoutPanel1); // add TableLayoutPanel to your panel
tableLayoutPanel1.Controls.Add(label1, 0, 0); // Add your label to TableLayout
</code>```

And set properties on Label:

```<code>label1.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
label1.AutoSize = true;
label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
</code>```

Now you can set

```<code>tableLayoutPanel1.AutoSize = true;
</code>```

It is kind of tricky but should give you what you need.

Body:
I need a label to appear in the middle bottom (like 30px above the bottom line) of a panel, that also auto sizes to wrap the text depending on how long the text is.

So far I can only have the label auto size to wrap the text and have it docked at the bottom. But it is at bottom left and not middle.
As is on this example Long Text Image and Image of short text I'd like to center
(sorry the text is not clear but its at the bottom in white)

I was able to achieve the auto size using the ClientSizeChanged event as below.

private void Panel1_ClientSizeChanged(object sender, EventArgs e)
    {
        label8.MaximumSize = new Size((sender as Control).ClientSize.Width - label8.Left, 10000);
    }

How do I have the text at the middle? It should be able to maintain the bottom middle (dock) position as I resize the panel.

Body:
Try following:

To your panel add TableLayoutPanel with following Properties:

tableLayoutPanel1.AutoSize = true; // This can be set at the end if you use designer
tableLayoutPanel1.ColumnCount = 1;
tableLayoutPanel1.RowCount = 1;
tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom;
panel1.Controls.Add(tableLayoutPanel1); // add TableLayoutPanel to your panel
tableLayoutPanel1.Controls.Add(label1, 0, 0); // Add your label to TableLayout

And set properties on Label:

label1.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
label1.AutoSize = true;
label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;

Now you can set

tableLayoutPanel1.AutoSize = true;

It is kind of tricky but should give you what you need.


来源: stackexchange

问:
Cannot Insert into Extended VARCHAR2 using JDBCTemplate
The need arose to store in excess of 4000 bytes into VARCHAR2 in Oracle database. The workaround was to engage the 'Extended Data Types'on the database to increase capacity. I am storing a maximum of 2000 characters but the special characters I'm inserting are up to 3 bytes each.

http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF55623

Manual insertion using SQLDeveloper or a SQL statement works fine. Tested with 2000 characters / 6000 bytes.

However, when attempting to insert any String over 4000 bytes using NamedParameterJdbcTemplate, I receive the following error:

Caused by: java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column

This leads me to believe that it is a driver issue of some type. I'm using dependency:

```<code>    <dependency>
        <groupId>com.oracle.weblogic</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>10.3.6.0</version>
    </dependency>
</code>```

Code:

```<code>@Override
public Number createRecord(Number incidentId, String type,
String verbatim, String createdBy) {
     MapSqlParameterSource parameters = new MapSqlParameterSource();
     parameters.addValue(MyConstants.MAP_VERBATIM, verbatim);
     namedTemplate.update(insertRecordSql, parameters, key, new
     String[]{"VERBATIM_ID"});
     return key.getKey();
}
</code>```

Column definition:

"VERBATIM" VARCHAR2(2000 CHAR) NOT NULL ENABLE

答: Your maven entry looks strange. You are trying to utilize oracle 12c enhancement but still, you are using jar from oracle 10 <version>10.3.6.0</version> . Moreover if you jdk is higher than jdk6 you probably you have to use ojdbc7

ContentLicense: CC BY-SA 3.0

Body:
The need arose to store in excess of 4000 bytes into VARCHAR2 in Oracle database. The workaround was to engage the 'Extended Data Types'on the database to increase capacity. I am storing a maximum of 2000 characters but the special characters I'm inserting are up to 3 bytes each.

http://docs.oracle.com/database/121/SQLRF/sql_elements001.htm#SQLRF55623

Manual insertion using SQLDeveloper or a SQL statement works fine. Tested with 2000 characters / 6000 bytes.

However, when attempting to insert any String over 4000 bytes using NamedParameterJdbcTemplate, I receive the following error:

Caused by: java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column

This leads me to believe that it is a driver issue of some type. I'm using dependency:

    <dependency>
        <groupId>com.oracle.weblogic</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>10.3.6.0</version>
    </dependency>

Code:

@Override
public Number createRecord(Number incidentId, String type,
String verbatim, String createdBy) {
     MapSqlParameterSource parameters = new MapSqlParameterSource();
     parameters.addValue(MyConstants.MAP_VERBATIM, verbatim);
     namedTemplate.update(insertRecordSql, parameters, key, new
     String[]{"VERBATIM_ID"});
     return key.getKey();
}

Column definition:

"VERBATIM" VARCHAR2(2000 CHAR) NOT NULL ENABLE


问:
nginx add_header not working
I am having an intriguing problem where whenever I use add_header in my virtual host configuration on an ubuntu server running nginx with PHP and php-fpm it simply doesn't work and I have no idea what I am doing wrong. Here is my config file:

```<code>server {
    listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    root /var/www/example.com/webroot/;
    index index.html index.htm index.php;

    # Make site accessible from http://www.example.com/
    server_name www.example.com;

    # max request size
    client_max_body_size 20m;

    # enable gzip compression
    gzip             on;
    gzip_static      on;
    gzip_min_length  1000;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types       text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    add_header PS 1

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to index.html
            try_files $uri $uri/ /index.php?$query_string;
            # Uncomment to enable naxsi on this location
            # include /etc/nginx/naxsi.rules
    }

    location ~* \.(css|js|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|$
            # 1 year -> 31536000
            expires 500s;
            access_log off;
            log_not_found off;
            add_header Pragma public;
            add_header Cache-Control "max-age=31536000, public";
    }
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

            # With php5-cgi alone:
            #fastcgi_pass 127.0.0.1:9000;
            # With php5-fpm:
            fastcgi_pass unix:/var/run/example.sock;
            fastcgi_index index.php?$query_string;
            include fastcgi_params;

            # instead I want to get the value from Origin request header
    }

    # Deny access to hidden files
    location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
    }

    error_page 403 /403/;
}

server {
    listen 80;
    server_name example.com;
    rewrite     ^ http://www.example.com$request_uri? permanent;
}
</code>```

I've tried adding the headers to the other location sections but the result is the same.

Any help appreciated!!

答:
I had the issue of not getting the response header due to the response code not within the allowed range, unless you specify the "always" keyword after the header value.

From the official docs:

Adds the specified field to a response header provided that the response code equals 200, 201, 204, 206, 301, 302, 303, 304, 307, or 308. The value can contain variables.

Title: nginx add_header not working

Body:
I am having an intriguing problem where whenever I use add_header in my virtual host configuration on an ubuntu server running nginx with PHP and php-fpm it simply doesn't work and I have no idea what I am doing wrong. Here is my config file:

server {
    listen   80; ## listen for ipv4; this line is default and implied
    #listen   [::]:80 default ipv6only=on; ## listen for ipv6

    root /var/www/example.com/webroot/;
    index index.html index.htm index.php;

    # Make site accessible from http://www.example.com/
    server_name www.example.com;

    # max request size
    client_max_body_size 20m;

    # enable gzip compression
    gzip             on;
    gzip_static      on;
    gzip_min_length  1000;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types       text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
    add_header PS 1

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to index.html
            try_files $uri $uri/ /index.php?$query_string;
            # Uncomment to enable naxsi on this location
            # include /etc/nginx/naxsi.rules
    }

    location ~* \.(css|js|asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mpe|mpp|odb|odc|odf|odg|odp|ods|odt|ogg|ogv|$
            # 1 year -> 31536000
            expires 500s;
            access_log off;
            log_not_found off;
            add_header Pragma public;
            add_header Cache-Control "max-age=31536000, public";
    }
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

            # With php5-cgi alone:
            #fastcgi_pass 127.0.0.1:9000;
            # With php5-fpm:
            fastcgi_pass unix:/var/run/example.sock;
            fastcgi_index index.php?$query_string;
            include fastcgi_params;

            # instead I want to get the value from Origin request header
    }

    # Deny access to hidden files
    location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
    }

    error_page 403 /403/;
}

server {
    listen 80;
    server_name example.com;
    rewrite     ^ http://www.example.com$request_uri? permanent;
}

I've tried adding the headers to the other location sections but the result is the same.

Any help appreciated!!


问:
Running node.js tests locally in vstest.console.exe gives ... Error: An exception occurred while invoking executor 'executor://nodejstestexecutor/v1
I'm trying to get VSTS to run my Mocha unit tests, similar to how I've got them running in VS 2017.

I'm installed the Node JS Tools for Visual Studio and VS Test Explorer (after a restart) picks up the tests, and runs them.

But I can't get a VSTS build task to run them ???

Tried going through the notes on NTVS about running tests in VSTS but no joy getting it to work.

Moved onto the section about troubleshooting, and seeing if I can run the tests using my local vstest.console.exe ...

So far trying to run vstest ...

Error: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0\Node.js Tools\Microsoft.NodejsTools.targets" was not found

quick fix ... added a copy of directory ... C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\VisualStudio\v15.0\Node.js Tools ... to ... C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0

Error: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" was not found

quick fix ... added a copy of directory ... C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets ... to ... C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0

Error: Could not find a part of the path C:\Repos\smc\BasicAzureExpress\BasicAzureExpress\ntvs\TestFrameworks

quick fix ... amend .nsproj to VS 2017 ... <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion> and a directory \TestFrameworks under \ntvs

... and then have the error ... Error: Missing generic test framework

So I'm left puzzled as to why VS 2017 can run the tests, but vstest.console.exe won't

答:
First, the VSToolsPath value is empty if running in command line, then uses $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) path, but there aren’t necessary files of nodejs tool.

You can modify it like this (change Community to Professional if you are using vs2017 Professional):

```<code><!--<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>-->
    <VSToolsPath>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\VisualStudio\v15.0</VSToolsPath>
</code>```

Secondly, refer to these steps to run test on Hosted VS 2017 agent.

Modify project file (njsproj)

：

```<code><!--<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>-->
    <VSToolsPath>C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0</VSToolsPath>
</code>```

Copy NodeJsTools content in C:\Program Files (x86)\Microsoft Visual Studio\2017[Community, professional or enterprise]\Common7\IDE\Extensions\Microsoft to your ntvs folder

Add these files to source control and check in changes

Queue build with Hosted VS 2017 agent.

Body:
First, the VSToolsPath value is empty if running in command line, then uses $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) path, but there aren’t necessary files of nodejs tool.

You can modify it like this (change Community to Professional if you are using vs2017 Professional):

<!--<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>-->
    <VSToolsPath>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\VisualStudio\v15.0</VSToolsPath>

Secondly, refer to these steps to run test on Hosted VS 2017 agent.

Modify project file (njsproj)

：

<!--<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>-->
    <VSToolsPath>C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0</VSToolsPath>

Copy NodeJsTools content in C:\Program Files (x86)\Microsoft Visual Studio\2017[Community, professional or enterprise]\Common7\IDE\Extensions\Microsoft to your ntvs folder

Add these files to source control and check in changes

Queue build with Hosted VS 2017 agent.


问:
Private constructor and inheritance (Java)
I have first class for which constructor takes a parameter.

```<code>public class First {
    First(Object o){
        o.toString();
    }
}
</code>```

I have a second class which extends this first one.

```<code>public class Second extends First {
    Second(Object o) {
        super(o);
    }
}
</code>```

What I want is to keep the constructor of Second class private in order to have a possibility to instantiate the only one instance of this class (using Singleton pattern, for instance), but compiler doesn't allow me to do that.

If I can't set the constructor as private here, what can I do to allow the only one instance of the class to be created?

答:
Here it is working !!</p>

```<code>class First {
    First(Object o){
        o.toString();
    }

   public First() {//I think you missed this
   }
}
class Second extends First {
  private static Second obj ;
    private Second(Object o) {
        super(o);
  }

  private Second() {

  }

    public static Second getInstance(){
        if(obj == null){
            obj = new Second(new Object());
        }
        return obj;
    }

}
public class SingleTon {
    public static void main(String[] args) {
        Second sObj = Second.getInstance();
    }
}
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I have first class for which constructor takes a parameter.

public class First {
    First(Object o){
        o.toString();
    }
}

I have a second class which extends this first one.

public class Second extends First {
    Second(Object o) {
        super(o);
    }
}

What I want is to keep the constructor of Second class private in order to have a possibility to instantiate the only one instance of this class (using Singleton pattern, for instance), but compiler doesn't allow me to do that.

If I can't set the constructor as private here, what can I do to allow the only one instance of the class to be created?

Body:
Here it is working !!

class First {
    First(Object o){
        o.toString();
    }

   public First() {//I think you missed this
   }
}
class Second extends First {
  private static Second obj ;
    private Second(Object o) {
        super(o);
  }

  private Second() {

  }

    public static Second getInstance(){
        if(obj == null){
            obj = new Second(new Object());
        }
        return obj;
    }

}
public class SingleTon {
    public static void main(String[] args) {
        Second sObj = Second.getInstance();
    }
}


问:
HTML, CSS: Make table vertically scrollable
I have a table that is dynamically created after an AJAX request (using vue.js). The number of columns and width of each column is calculated.

My problem is, that there should be a vertical scrollbar when theres not enough space in the table, but even when setting style="width: 600px; overflow-x: scroll" no scrollbar shows up and the header elements gets shrinked together to the width of the wrapper div and the table rows get clipped.

Heres my relevant code (using bootstrap and vue.js 2):

```<code>    <div class="panel-body" id="datatable">
        <table class="table data-table" id="datatable-content">
            <thead class="datatable-head" id="datatable-head">
                <tr>
                    <th v-for="value in tableHeader" v-text="value"></th>
                </tr>
            </thead>

            <tbody class="datatable-body" id="datatable-body">
                <tr v-for="row in tableRows">
                    <td v-for="key in tableHeader" v-html="highlightFilterString(row[key])"></td>
                </tr>
            </tbody>
        </table>
    </div>
</code>```

and the css:

```<code>    .data-table {
        overflow-x: scroll;
        display: block;
        width: 100%;
    }
    .datatable-body {
        display:block;
        height: calc(100vh - 118px);/
        overflow-y: scroll;
        overflow-x: hidden;
    }
    .datatable-head {
        display:block;
        overflow-x: scroll;
    }
    .datatable-head, .datatable-body tr {
        min-width: 100px;
        text-align: center;
    }
    .datatable-body td {
        min-width: 100px;
        text-align: center;
    }
    .datatable-head th {
        min-width: 100px;
        text-align: center;
    }
</code>```

What is the problem here?

答:
I commented out the overflow-x element and it seems to be working fine now. Made fiddle with static html content

https://jsfiddle.net/v7qpot2b/

```<code> .datatable-body {
        display:block;
        height: calc(100vh - 118px);/
        overflow-y: scroll;
        /* overflow-x: hidden; */
    }
</code>```

Body:
I have a table that is dynamically created after an AJAX request (using vue.js). The number of columns and width of each column is calculated.

My problem is, that there should be a vertical scrollbar when theres not enough space in the table, but even when setting style="width: 600px; overflow-x: scroll" no scrollbar shows up and the header elements gets shrinked together to the width of the wrapper div and the table rows get clipped.

Heres my relevant code (using bootstrap and vue.js 2):

and the css:

    .data-table {
        overflow-x: scroll;
        display: block;
        width: 100%;
    }
    .datatable-body {
        display:block;
        height: calc(100vh - 118px);/
        overflow-y: scroll;
        overflow-x: hidden;
    }
    .datatable-head {
        display:block;
        overflow-x: scroll;
    }
    .datatable-head, .datatable-body tr {
        min-width: 100px;
        text-align: center;
    }
    .datatable-body td {
        min-width: 100px;
        text-align: center;
    }
    .datatable-head th {
        min-width: 100px;
        text-align: center;
    }

What is the problem here?

Body:
I commented out the overflow-x element and it seems to be working fine now. Made fiddle with static html content

https://jsfiddle.net/v7qpot2b/

 .datatable-body {
        display:block;
        height: calc(100vh - 118px);/
        overflow-y: scroll;
        /* overflow-x: hidden; */
    }


问:
Data from a DataGridView Configured on Another Form
I have Form1 that has a dataGridView and a button to add contents to that Grid. When selecting this button, I call Form2 which has 2 TextBox and a ComboBox to populate the Name, Directory and Format (for example), plus an OK button to add the row to the dataGridView on Form1.

When I get back on Form1, the dataGridView must be showing the content entered. What happens is that my Grid has three columns: Name, Format and a button column to, when clicking it, reload that screen of Form2 with the previously filled information loaded again in each field to be able to change or just consult.

Firstly I tried to create a function to add the lines to my Grid by parameters, as shown in the code below:

Eu tenho o Form1 que possui uma dataGridView e um botão para adicionar conteúdos nessa Grid. Ao selecionar esse botão, eu chamo o Form2 que possui 2 TextBox e um ComboBox para preencher o Nome, Diretório e Formato (por exemplo), além de um botão OK para adicionar a linha a dataGridView na Form1.

Form 1

```<code>public Form1()
{
    InitializeComponent();
}

public void AddRows(string name, string path)
{
    dataGridView1.Rows.Add(name, path);
    dataGridView1.Update();
}
</code>```

Form 2

```<code>public Form2()
{
    InitializeComponent();
}

private void bt1_Click(object sender, EventArgs e)
{
    var nome = txt_name.Text;
    var path = txt_path.Text;

    var form1 = new Form1();
    form1.AddRows(name, path);
}
</code>```

However, it ended up not working, showing nothing on the Grid. So I thought about creating a class with a name, path and format method (get and set for each) to store everything in a list of objects (I think that's it, forgive me if I'm wrong because I'm a beginner). Or save to a DataSet. But then I thought, I instantiate the class in my Form2 and pass the values filled in the fields, but then, what do I do in my Form1?

I think it's all very confusing, I'd appreciate it if someone could explain a clearer method of resolving this situation and please be very specific since I'm a beginner.

答:
It is not exactly clear what you are trying to achieve. It appears you have two forms. On form (form1) there is a DataGridView and a Button to add new rows to the grid. On the second form (form2) there are two text boxes and a combo box and a button for “OK”. I am guessing the text boxes are used to allow the user to enter a new “Name” and “Format” data. Then, when the user clicks the “OK” button, the data in the text boxes are added to a new row of the DataGridView in form1. Finally, the “Edit” button on each row of the DataGridView allows the user to open the SAME form2 (used to add new items) and use it to edit the row the user clicked.

I hope I understand this correctly. This is doable and there are many ways to achieve this. I can only assume there is SOME reason you would not simply “add” or “edit” these cells directly in the grid. The default behavior of the DataGridView to “add new rows” or “edit cells” is already implemented and there is no need for a form2 to do this when you can achieve the same thing without a new form2 and absolutely no code is needed. Therefore, I will assume there is a reason you can not edit the cells directly in the grid. Having a DataSource could be a reason (see below)…

The answer below is ONE way to achieve this. I must give a warning if there is a DataSource with the DataGridView. You can use this approach however, whenever the code below adds or edits cells in the grid, it does so by directly accessing the grids cells. This will NOT work if there is a DataSource attached to the grid. If there is a DataSource, then when the code below adds or edits items, you would need to change the code to do these add/edit operations to the DataSource and NOT the grid itself.

Most of the work can be done in Form2. In both an “Add” or “Edit” situation Form2 is going to need at least ONE item from Form1… that would be Form1’s DataGridView. Using the “Add” method as an example, it is going to need Form1’s DataGridView in order to add a new row. This can be achieved by simply creating a new constructor for Form2 that takes a DataGridView in its signature. The code below is how you would call this new constructor from Form1’s btnAdd_Click event.

```<code>private void btnAdd_Click(object sender, EventArgs e) {
  Form2 f2 = new Form2(dataGridView1);
  f2.ShowDialog();
}
</code>```

Now we need to make this constructor in Form2. Since the new row will not be added until the user presses the “Add/OK” button, we need to save Fom1’s DataGridView passed in by the constructor. Therefore a global DataGridView variable parentDGV is created. When the constructor is called we simply need to set parentDGV to the passed in DataGridView. This will allow access to the grid in the “Add” method.

```<code>DataGridView parentDGV;

public Form2(DataGridView dgv) {
  parentDGV = dgv;
  InitializeComponent();
}
</code>```

Since we now have access to Form1’s DataGridView you could simply add the new row. No error checking is done so the text boxes may be empty. Below is Form2’s “Add” button click event.

```<code>private void btnAddToGrid_Click(object sender, EventArgs e) {
  parentDGV.Rows.Add(txtName.Text, txtFormat.Text);
}
</code>```

This should allow the user to add a new row of data in Form1’s DataGridView from Form2’s “Add” button.

Next, we need to take care of the “Edit” buttons on each row of the DataGridView. If you want to use the same Form2 to edit rows, then you will need to make some changes since it currently will only add rows. To make Form2 work properly, it will need to know if the user clicked the “Edit” or “Add” button on Form1. One way to achieve this is to make another constructor for Form2. This constructor will obviously need Form1’s DataGridView, but also it will need a “Row” index of the “Edit” button clicked. This will give us the row index of the row to edit. We can make a global int variable “editRowIndex” to allow access from other methods in Form2.

```<code>DataGridView parentDGV;
int editRowIndex;

public Form2(DataGridView dgv, int rowIndex) {
  parentDGV = dgv;
  editRowIndex = rowIndex;
  InitializeComponent();
  SetEditForm();
}
</code>```

The SetEditForm method makes some cosmetic changes to the form by filling the text boxes with the data to edit, changes the “Add” button text to “Update” and more importantly, changes the buttons “Click” event handler to update the row in the grid instead of adding a new row.

```<code>private void SetEditForm() {
  btnAddToGrid.Text = "Update";
  this.btnAddToGrid.Click -= this.btnAddToGrid_Click;
  this.btnAddToGrid.Click += new System.EventHandler(this.btnAddToGrid_EditClick);
  if (parentDGV.Rows[editRowIndex].Cells["AName"].Value != null)
    txtName.Text = parentDGV.Rows[editRowIndex].Cells["AName"].Value.ToString();
  else
    txtName.Text = "";

  if (parentDGV.Rows[editRowIndex].Cells["Format"].Value != null)
    txtFormat.Text = parentDGV.Rows[editRowIndex].Cells["Format"].Value.ToString();
  else
    txtFormat.Text = "";
  // set combo box value
}
</code>```

Below is the EditClick event to update the proper row in the grid with the new data from Form2 text boxes. I assume once the user is done editing, the form would close.

```<code>private void btnAddToGrid_EditClick(object sender, EventArgs e) {
  parentDGV.Rows[editRowIndex].Cells["AName"].Value = txtName.Text;
  parentDGV.Rows[editRowIndex].Cells["Format"].Value = txtFormat.Text;
  this.Close();
}
</code>```

Finally, the last part to take care of is when the user clicks an “Edit” button, on one of the rows in Form1’s DataGridview. To handle this the DataGridView’s CellClick event is wired up. Once the clicked cell is determined to be the “Edit” button, we simply create the new Form2 with the proper constructor.

```<code>private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  if ((e.RowIndex >= 0) && (!dataGridView1.Rows[e.RowIndex].IsNewRow) ) {
    if (e.ColumnIndex >= 0) {
      if (dataGridView1.Columns[e.ColumnIndex].Name == "Edit") {
        Form2 f2 = new Form2(dataGridView1, e.RowIndex);
        f2.ShowDialog();
      }
    }
  }
}
</code>```

I hope this makes sense. Putting it all together… Using the “Designer”… Form1 has a DataGridView with two text box columns (AName, Format) and a third button column (Edit) to edit the row via Form2. Also, Form1 has a button to “Add” a new row via Form2

```<code>public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  FillGrid();
}

private void FillGrid() {
  dataGridView1.Rows.Add("Cell00Data", "Cell01Data");
  dataGridView1.Rows.Add("Cell10Data", "Cell11Data");
  dataGridView1.Rows.Add("Cell20Data", "Cell21Data");
  dataGridView1.Rows.Add("Cell30Data", "Cell31Data");
}

private void btnAdd_Click(object sender, EventArgs e) {
  Form2 f2 = new Form2(dataGridView1);
  f2.ShowDialog();
}

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  if ((e.RowIndex >= 0) && (!dataGridView1.Rows[e.RowIndex].IsNewRow) ) {
    if (e.ColumnIndex >= 0) {
      if (dataGridView1.Columns[e.ColumnIndex].Name == "Edit") {
        Form2 f2 = new Form2(dataGridView1, e.RowIndex);
        f2.ShowDialog();
      }
    }
  }
}
</code>```

Form2: Using the ‘Designer, Form2 has two text boxes (txtName, txtFormat) for “Name” and “Format”, a Button to either “Add” the info as a new item or “Update” a row in the grid.

```<code>DataGridView parentDGV;
int editRowIndex;

// Constructor to Add a new row
public Form2(DataGridView dgv) {
  parentDGV = dgv;
  InitializeComponent();
}
// Constructor to Edit a row
public Form2(DataGridView dgv, int rowIndex) {
  parentDGV = dgv;
  editRowIndex = rowIndex;
  InitializeComponent();
  SetEditForm();
}
// update form for edit mode
private void SetEditForm() {
  btnAddToGrid.Text = "Update";
  this.btnAddToGrid.Click -= this.btnAddToGrid_Click;
  this.btnAddToGrid.Click += new System.EventHandler(this.btnAddToGrid_EditClick);
  if (parentDGV.Rows[editRowIndex].Cells["AName"].Value != null)
    txtName.Text = parentDGV.Rows[editRowIndex].Cells["AName"].Value.ToString();
  else
    txtName.Text = "";

  if (parentDGV.Rows[editRowIndex].Cells["Format"].Value != null)
    txtFormat.Text = parentDGV.Rows[editRowIndex].Cells["Format"].Value.ToString();
  else
    txtFormat.Text = "";
  // set combo box value
}

// Button click event to update form1’s grid
private void btnAddToGrid_EditClick(object sender, EventArgs e) {
  parentDGV.Rows[editRowIndex].Cells["AName"].Value = txtName.Text;
  parentDGV.Rows[editRowIndex].Cells["Format"].Value = txtFormat.Text;
  this.Close();
}

// Button click event to add a row to form1’s grid
private void btnAddToGrid_Click(object sender, EventArgs e) {
  parentDGV.Rows.Add(txtName.Text, txtFormat.Text);
}
</code>```

Body:
I have Form1 that has a dataGridView and a button to add contents to that Grid. When selecting this button, I call Form2 which has 2 TextBox and a ComboBox to populate the Name, Directory and Format (for example), plus an OK button to add the row to the dataGridView on Form1.

When I get back on Form1, the dataGridView must be showing the content entered. What happens is that my Grid has three columns: Name, Format and a button column to, when clicking it, reload that screen of Form2 with the previously filled information loaded again in each field to be able to change or just consult.

Firstly I tried to create a function to add the lines to my Grid by parameters, as shown in the code below:

Eu tenho o Form1 que possui uma dataGridView e um botão para adicionar conteúdos nessa Grid. Ao selecionar esse botão, eu chamo o Form2 que possui 2 TextBox e um ComboBox para preencher o Nome, Diretório e Formato (por exemplo), além de um botão OK para adicionar a linha a dataGridView na Form1.

Form 1

public Form1()
{
    InitializeComponent();
}

public void AddRows(string name, string path)
{
    dataGridView1.Rows.Add(name, path);
    dataGridView1.Update();
}

Form 2

public Form2()
{
    InitializeComponent();
}

private void bt1_Click(object sender, EventArgs e)
{
    var nome = txt_name.Text;
    var path = txt_path.Text;

    var form1 = new Form1();
    form1.AddRows(name, path);
}

However, it ended up not working, showing nothing on the Grid. So I thought about creating a class with a name, path and format method (get and set for each) to store everything in a list of objects (I think that's it, forgive me if I'm wrong because I'm a beginner). Or save to a DataSet. But then I thought, I instantiate the class in my Form2 and pass the values filled in the fields, but then, what do I do in my Form1?

I think it's all very confusing, I'd appreciate it if someone could explain a clearer method of resolving this situation and please be very specific since I'm a beginner.

Body:
It is not exactly clear what you are trying to achieve. It appears you have two forms. On form (form1) there is a DataGridView and a Button to add new rows to the grid. On the second form (form2) there are two text boxes and a combo box and a button for “OK”. I am guessing the text boxes are used to allow the user to enter a new “Name” and “Format” data. Then, when the user clicks the “OK” button, the data in the text boxes are added to a new row of the DataGridView in form1. Finally, the “Edit” button on each row of the DataGridView allows the user to open the SAME form2 (used to add new items) and use it to edit the row the user clicked.

I hope I understand this correctly. This is doable and there are many ways to achieve this. I can only assume there is SOME reason you would not simply “add” or “edit” these cells directly in the grid. The default behavior of the DataGridView to “add new rows” or “edit cells” is already implemented and there is no need for a form2 to do this when you can achieve the same thing without a new form2 and absolutely no code is needed. Therefore, I will assume there is a reason you can not edit the cells directly in the grid. Having a DataSource could be a reason (see below)…

The answer below is ONE way to achieve this. I must give a warning if there is a DataSource with the DataGridView. You can use this approach however, whenever the code below adds or edits cells in the grid, it does so by directly accessing the grids cells. This will NOT work if there is a DataSource attached to the grid. If there is a DataSource, then when the code below adds or edits items, you would need to change the code to do these add/edit operations to the DataSource and NOT the grid itself.

Most of the work can be done in Form2. In both an “Add” or “Edit” situation Form2 is going to need at least ONE item from Form1… that would be Form1’s DataGridView. Using the “Add” method as an example, it is going to need Form1’s DataGridView in order to add a new row. This can be achieved by simply creating a new constructor for Form2 that takes a DataGridView in its signature. The code below is how you would call this new constructor from Form1’s btnAdd_Click event.

private void btnAdd_Click(object sender, EventArgs e) {
  Form2 f2 = new Form2(dataGridView1);
  f2.ShowDialog();
}

Now we need to make this constructor in Form2. Since the new row will not be added until the user presses the “Add/OK” button, we need to save Fom1’s DataGridView passed in by the constructor. Therefore a global DataGridView variable parentDGV is created. When the constructor is called we simply need to set parentDGV to the passed in DataGridView. This will allow access to the grid in the “Add” method.

DataGridView parentDGV;

public Form2(DataGridView dgv) {
  parentDGV = dgv;
  InitializeComponent();
}

Since we now have access to Form1’s DataGridView you could simply add the new row. No error checking is done so the text boxes may be empty. Below is Form2’s “Add” button click event.

private void btnAddToGrid_Click(object sender, EventArgs e) {
  parentDGV.Rows.Add(txtName.Text, txtFormat.Text);
}

This should allow the user to add a new row of data in Form1’s DataGridView from Form2’s “Add” button.

Next, we need to take care of the “Edit” buttons on each row of the DataGridView. If you want to use the same Form2 to edit rows, then you will need to make some changes since it currently will only add rows. To make Form2 work properly, it will need to know if the user clicked the “Edit” or “Add” button on Form1. One way to achieve this is to make another constructor for Form2. This constructor will obviously need Form1’s DataGridView, but also it will need a “Row” index of the “Edit” button clicked. This will give us the row index of the row to edit. We can make a global int variable “editRowIndex” to allow access from other methods in Form2.

DataGridView parentDGV;
int editRowIndex;

public Form2(DataGridView dgv, int rowIndex) {
  parentDGV = dgv;
  editRowIndex = rowIndex;
  InitializeComponent();
  SetEditForm();
}

The SetEditForm method makes some cosmetic changes to the form by filling the text boxes with the data to edit, changes the “Add” button text to “Update” and more importantly, changes the buttons “Click” event handler to update the row in the grid instead of adding a new row.

private void SetEditForm() {
  btnAddToGrid.Text = "Update";
  this.btnAddToGrid.Click -= this.btnAddToGrid_Click;
  this.btnAddToGrid.Click += new System.EventHandler(this.btnAddToGrid_EditClick);
  if (parentDGV.Rows[editRowIndex].Cells["AName"].Value != null)
    txtName.Text = parentDGV.Rows[editRowIndex].Cells["AName"].Value.ToString();
  else
    txtName.Text = "";

  if (parentDGV.Rows[editRowIndex].Cells["Format"].Value != null)
    txtFormat.Text = parentDGV.Rows[editRowIndex].Cells["Format"].Value.ToString();
  else
    txtFormat.Text = "";
  // set combo box value
}

Below is the EditClick event to update the proper row in the grid with the new data from Form2 text boxes. I assume once the user is done editing, the form would close.

private void btnAddToGrid_EditClick(object sender, EventArgs e) {
  parentDGV.Rows[editRowIndex].Cells["AName"].Value = txtName.Text;
  parentDGV.Rows[editRowIndex].Cells["Format"].Value = txtFormat.Text;
  this.Close();
}

Finally, the last part to take care of is when the user clicks an “Edit” button, on one of the rows in Form1’s DataGridview. To handle this the DataGridView’s CellClick event is wired up. Once the clicked cell is determined to be the “Edit” button, we simply create the new Form2 with the proper constructor.

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  if ((e.RowIndex >= 0) && (!dataGridView1.Rows[e.RowIndex].IsNewRow) ) {
    if (e.ColumnIndex >= 0) {
      if (dataGridView1.Columns[e.ColumnIndex].Name == "Edit") {
        Form2 f2 = new Form2(dataGridView1, e.RowIndex);
        f2.ShowDialog();
      }
    }
  }
}

I hope this makes sense. Putting it all together… Using the “Designer”… Form1 has a DataGridView with two text box columns (AName, Format) and a third button column (Edit) to edit the row via Form2. Also, Form1 has a button to “Add” a new row via Form2

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  FillGrid();
}

private void FillGrid() {
  dataGridView1.Rows.Add("Cell00Data", "Cell01Data");
  dataGridView1.Rows.Add("Cell10Data", "Cell11Data");
  dataGridView1.Rows.Add("Cell20Data", "Cell21Data");
  dataGridView1.Rows.Add("Cell30Data", "Cell31Data");
}

private void btnAdd_Click(object sender, EventArgs e) {
  Form2 f2 = new Form2(dataGridView1);
  f2.ShowDialog();
}

private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) {
  if ((e.RowIndex >= 0) && (!dataGridView1.Rows[e.RowIndex].IsNewRow) ) {
    if (e.ColumnIndex >= 0) {
      if (dataGridView1.Columns[e.ColumnIndex].Name == "Edit") {
        Form2 f2 = new Form2(dataGridView1, e.RowIndex);
        f2.ShowDialog();
      }
    }
  }
}

Form2: Using the ‘Designer, Form2 has two text boxes (txtName, txtFormat) for “Name” and “Format”, a Button to either “Add” the info as a new item or “Update” a row in the grid.

DataGridView parentDGV;
int editRowIndex;

// Constructor to Add a new row
public Form2(DataGridView dgv) {
  parentDGV = dgv;
  InitializeComponent();
}
// Constructor to Edit a row
public Form2(DataGridView dgv, int rowIndex) {
  parentDGV = dgv;
  editRowIndex = rowIndex;
  InitializeComponent();
  SetEditForm();
}
// update form for edit mode
private void SetEditForm() {
  btnAddToGrid.Text = "Update";
  this.btnAddToGrid.Click -= this.btnAddToGrid_Click;
  this.btnAddToGrid.Click += new System.EventHandler(this.btnAddToGrid_EditClick);
  if (parentDGV.Rows[editRowIndex].Cells["AName"].Value != null)
    txtName.Text = parentDGV.Rows[editRowIndex].Cells["AName"].Value.ToString();
  else
    txtName.Text = "";

  if (parentDGV.Rows[editRowIndex].Cells["Format"].Value != null)
    txtFormat.Text = parentDGV.Rows[editRowIndex].Cells["Format"].Value.ToString();
  else
    txtFormat.Text = "";
  // set combo box value
}

// Button click event to update form1’s grid
private void btnAddToGrid_EditClick(object sender, EventArgs e) {
  parentDGV.Rows[editRowIndex].Cells["AName"].Value = txtName.Text;
  parentDGV.Rows[editRowIndex].Cells["Format"].Value = txtFormat.Text;
  this.Close();
}

// Button click event to add a row to form1’s grid
private void btnAddToGrid_Click(object sender, EventArgs e) {
  parentDGV.Rows.Add(txtName.Text, txtFormat.Text);
}


问:
DNS Round Robin very slow requests in failover scenario
Currently i'm configuring a server pool with AWS. It is a simple setup with two database servers an scalable server array and two load balancers in front of it all. Every machine has a failover standing by and it should all be pretty robust.

The load balancers should be able to failover through Round Robin DNS. So in a happy day scenario both machines get hit and distribute the traffic over the array. When one of these machines is down Round Robin DNS in combination with client browser retry should make it so that browsers should shift their target host to the machine which is still up once they hit a timeout. This is not something I came up with but seems like a very good solution.

The problem i'm experiencing is as following. The shift does actually happen but not just once for the failed request but for each and every subsequent request from the same browser. So a simple page request takes 21 seconds to load after which all images also take 21 seconds to load. All the following page request also takes this long. So the failover works but is a the same time completely useless.

Output from a dig:

; <<>> DiG 9.6.1-P2 <<>> example.com

;; global options: +cmd

;; Got answer:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45224

;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:

;example.com.             IN      A

;; ANSWER SECTION:

www.example.com.      86400   IN      A       1.2.3.4

www.example.com.      86400   IN      A       1.2.3.4

;; Query time: 31 msec

;; SERVER: 172.16.0.23#53(172.16.0.23)

;; WHEN: Mon Dec 20 12:21:25 2010

;; MSG SIZE  rcvd: 67

Thanks in advance!

Maarten Hoekstra

Kingsquare Information Services

答: There is a reason we call this "poor man's load balancing."  It does work but you are the mercy of the resolver, and the time outs depending upon which IP is returned first from your dns servers.  You can look at something like  dnsmadeeasy.com  and their dns failover (there are others that do this, but dnsmadeeasy is the one I know of). Basically they monitor app availability and can fast flux the dns changes in regards to application state.. </p>


问:
Pagination of UIViews on Screen - Swift
I am trying to implement scrollable list of UIViews.

As shown in screenshot above, there is 3 buttons shown on the screen. I am trying create a list of uiViews, that user can scroll them 3 at a time.

I have implemented this in UICollection. The problem is user can scroll freely throw items. I want him to be able to scroll 3 at a time.

Is it possible with UICollection or should I use another component ?

答: You just need to enable paging for the UICollectionView. Just check the box saying Paging Enabled in the attributes inspector. You can limit the number of cells to three by returning 1/3rd of the collectionview's width in the sizeForItemAt Flowlayout delegate method of the collectionview.

Title: Pagination of UIViews on Screen - Swift


问:
Visual Studio Native Testing: Writing to a file after all tests have run
I use the CppUnitTestFramework of Visual Studio 2015 to run a number of tests on my C++ code, which is working. However, after all tests have run I want to write some results into a file. I tried the following approach via TEST_CLASS_CLEANUP:

```<code>TEST_CLASS_CLEANUP(CleanUp) {
  std::ofstream outFile("compare.html");
  outFile << "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/></head><body><table>";

  //Write some stuff to outFile
  ...

  outFile << "</body></html>" << std::endl;
  outFile.close();
}
</code>```

However, the file "compare.html" is not created anywhere. When I use TEST_METHOD_CLEANUP instead, it's working, but writes after every test, which is not intended. So, can I write to a file somehow from TEST_CLASS_CLEANUP?

答:
Yes, you can. Actually, you code works fine and creates a file. See example:</p>

```<code>TEST_CLASS(Example)
{
public:
    TEST_METHOD(ExampleTest)
    {
        // A test
    }

private:
    TEST_CLASS_CLEANUP(ExampleCleanUp)
    {
        std::ofstream outFile("compare.html");
        outFile << "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/></head><body><table>";

        outFile << "</body></html>" << std::endl;
        outFile.close();
    }
};
</code>```

Body:
I use the CppUnitTestFramework of Visual Studio 2015 to run a number of tests on my C++ code, which is working. However, after all tests have run I want to write some results into a file. I tried the following approach via TEST_CLASS_CLEANUP:

TEST_CLASS_CLEANUP(CleanUp) {
  std::ofstream outFile("compare.html");
  outFile << "<!DOCTYPE html><meta charset=\"utf-8\"/>
";

  //Write some stuff to outFile
  ...

  outFile << "" << std::endl;
  outFile.close();
}

However, the file "compare.html" is not created anywhere. When I use TEST_METHOD_CLEANUP instead, it's working, but writes after every test, which is not intended. So, can I write to a file somehow from TEST_CLASS_CLEANUP?

Body:
Yes, you can. Actually, you code works fine and creates a file. See example:

TEST_CLASS(Example)
{
public:
    TEST_METHOD(ExampleTest)
    {
        // A test
    }

private:
    TEST_CLASS_CLEANUP(ExampleCleanUp)
    {
        std::ofstream outFile("compare.html");
        outFile << "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/></head><body><table>";

        outFile << "</body></html>" << std::endl;
        outFile.close();
    }
};


问:
Gatling Performance and load testing with Camunda BPMN
I am working on an application using Camunda BPMN. This application calls restful
services for fetching or saving or updating data in the backend. I want to write load performance tests for this application. I am able to test indivisual endpoints with scala scripts in gatling. But how to test one entire BPMN workflow ? Is there any headstart material that I can refer?</p>

答:
Load and performance testing is a very complicated topic and usually depends on number of external environment factors.

I think a good starting point would be a user guide and our examples repository to get general idea on testing practices.

Once you have chosen your way of testing the whole process you then would have to identify parameters that simulate high load in your environment and adjust them in your test.


问:
GDax API GET request always returns Error 400
I'm trying to get the order book from GDAX (link to documentation of the call) but when doing it from the c# executable I always get Error 400 - Bad request.

When taking the actual URL and pasting it into my browser, it works fine.

```<code>String URL = "https://api.gdax.com/products/BTC-USD/book?level=2";
WebRequest request = WebRequest.Create(URL);
WebResponse response = request.GetResponse();
</code>```

答:
The actual issue with your API call is , the API is expecting a user-agent string while making the request: Below is the code in working condition:

```<code>        try
        {

            String URL = "http://api.gdax.com/products/BTC-USD/book?level=2";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.UserAgent = ".NET Framework Test Client";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            var encoding = ASCIIEncoding.ASCII;
            using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
            {
                string responseText = reader.ReadToEnd();
            }

        }
        catch(WebException ex)
        {
            HttpWebResponse xyz = ex.Response as HttpWebResponse;
            var encoding = ASCIIEncoding.ASCII;
            using (var reader = new System.IO.StreamReader(xyz.GetResponseStream(), encoding))
            {
                string responseText = reader.ReadToEnd();
            }
        }
</code>```

Basically ProtocolError indicates that you have received the response but there is an error related to protocol, which you can observe, when you read the response content from exception. I have added catch to handle the exception and read ex.Response (which is HttpWebResponse) and could see that the API is asking for user-agent to be suppllied while making the call. I got to see the error as "{"message":"User-Agent header is required."}"

You can ignore the code inside the exception block, I used it only to see what is the actual response message, which contains actual error details

Note: I have boxed WebRequest to HttpWebRequest to have additional http protocol related properties and most importantly "UserAgent" property which is not available with the WebRequest class.

Body:
I'm trying to get the order book from GDAX (link to documentation of the call) but when doing it from the c# executable I always get Error 400 - Bad request.

When taking the actual URL and pasting it into my browser, it works fine.

String URL = "https://api.gdax.com/products/BTC-USD/book?level=2";
WebRequest request = WebRequest.Create(URL);
WebResponse response = request.GetResponse();

Body:
The actual issue with your API call is , the API is expecting a user-agent string while making the request: Below is the code in working condition:

        try
        {

            String URL = "http://api.gdax.com/products/BTC-USD/book?level=2";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.UserAgent = ".NET Framework Test Client";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            var encoding = ASCIIEncoding.ASCII;
            using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
            {
                string responseText = reader.ReadToEnd();
            }

        }
        catch(WebException ex)
        {
            HttpWebResponse xyz = ex.Response as HttpWebResponse;
            var encoding = ASCIIEncoding.ASCII;
            using (var reader = new System.IO.StreamReader(xyz.GetResponseStream(), encoding))
            {
                string responseText = reader.ReadToEnd();
            }
        }

Basically ProtocolError indicates that you have received the response but there is an error related to protocol, which you can observe, when you read the response content from exception. I have added catch to handle the exception and read ex.Response (which is HttpWebResponse) and could see that the API is asking for user-agent to be suppllied while making the call. I got to see the error as "{"message":"User-Agent header is required."}"

You can ignore the code inside the exception block, I used it only to see what is the actual response message, which contains actual error details

Note: I have boxed WebRequest to HttpWebRequest to have additional http protocol related properties and most importantly "UserAgent" property which is not available with the WebRequest class.


问:
Populate a column in SQL Server by weekday or weekend depending on the datetime
I am working on SQL Server, wherein I cannot update any existing column nor can I add any more data/ column to the data.

I have a column of dttime (yyyy-mm-dd hh:mm:ss) which consists of the date time value against each entry.
I want to select the existing columns , and a new column as wd which will be populated as 'weekend' when the day of the week is either Saturday or Sunday and 'weekday' in case of other days

I am using the below query:

```<code>SELECT id, total,
case when dayofweek(dttime) in (1,7) then 'Weekend' else 'Weekday' end as wd
from table_name
</code>```

Please suggest where is the mistake here, or is there any alternative to this, in case I have more than two different things to populate in a similar way, based on another column.

答:
You need DATEPART function. try this :

```<code>SELECT id, total,
case when DATEPART(dw,dttime) in (6,7) then 'Weekend' else 'Weekday' end as wd
from table_name
</code>```

Body:
I am working on SQL Server, wherein I cannot update any existing column nor can I add any more data/ column to the data.

I have a column of dttime (yyyy-mm-dd hh:mm:ss) which consists of the date time value against each entry.
I want to select the existing columns , and a new column as wd which will be populated as 'weekend' when the day of the week is either Saturday or Sunday and 'weekday' in case of other days

I am using the below query:

SELECT id, total,
case when dayofweek(dttime) in (1,7) then 'Weekend' else 'Weekday' end as wd
from table_name

Please suggest where is the mistake here, or is there any alternative to this, in case I have more than two different things to populate in a similar way, based on another column.

Body:
You need DATEPART function. try this :

SELECT id, total,
case when DATEPART(dw,dttime) in (6,7) then 'Weekend' else 'Weekday' end as wd
from table_name


问:
template class specialization : template-id does not match any template declaration
I'm trying to use templates, but couldn't understand what is wrong with below code.

solve.h

```<code>#include "nlp.h"
#include "Ipopt_solve.h"

enum algo_type {IPOPT =1, SQP};

template<int ALG>
class solve
{
public:
    solve()
    {
    }
};

template<>
class solve<IPOPT>
{
public:
    solve(nlp*);

private:
    Ipopt_solve m_ipopt;

};
</code>```

solve.cpp

```<code>template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}
</code>```

Ipopt_solve is a sub-class of an abstract class TNLP. Ipopt_solve is initialized with a reference to nlp class.

from main.cpp

```<code>nlp problem(&model);
solve<IPOPT> solution(&problem);
</code>```

I'm getting the error like shown below.

error: template-id 'solve<>' for 'solve<1>::solve(nlp*)' does not match any template declaration
 solve::solve(nlp* problem): m_ipopt(problem)

答:
This declaration in its original form

```<code>template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}
</code>```

is formally valid by itself. However, it is not doing what you think it is doing. This declaration declares an explicit specialization for a member of the main template

```<code>template<int ALG>
class solve
{
  ...
</code>```

It has no relation to your explicit specialization

```<code>template<>
class solve<IPOPT>
{
  ...
</code>```

The compiler is trying to specialize constructor solve<ALG>::solve(nlp* problem) of the main template. However, the main template has no such constructor. Hence the error message, that tells you exactly that: the compiler does not understand what constructor you are trying to specialize, it cannot find the matching member in the main template.

For example, you can use this syntax to explicitly specialize the default constructor of the main template

```<code>template<>
solve<SQP>::solve()
{
  // Specialized code for `solve<SQP>`'s default constructor
}
</code>```

This will compile fine since the main template does indeed have such constructor. (Note that you don't have to explicitly specialize the whole class for that, you can just explicitly specialize the constructor.)

Your intent was, obviously, completely different: to provide definition for the constructor in the class template specialization

```<code>template<>
class solve<IPOPT>
{
  ...
</code>```

The proper syntax for that should not mention template<>

```<code>solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}
</code>```

Body:
I'm trying to use templates, but couldn't understand what is wrong with below code.

solve.h

#include "nlp.h"
#include "Ipopt_solve.h"

enum algo_type {IPOPT =1, SQP};

template<int ALG>
class solve
{
public:
    solve()
    {
    }
};

template<>
class solve<IPOPT>
{
public:
    solve(nlp*);

private:
    Ipopt_solve m_ipopt;

};

solve.cpp

template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}

Ipopt_solve is a sub-class of an abstract class TNLP. Ipopt_solve is initialized with a reference to nlp class.

from main.cpp

nlp problem(&model);
solve<IPOPT> solution(&problem);

I'm getting the error like shown below.

error: template-id 'solve<>' for 'solve<1>::solve(nlp*)' does not match any template declaration
 solve::solve(nlp* problem): m_ipopt(problem)

Body:
This declaration in its original form

template<>
solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}

is formally valid by itself. However, it is not doing what you think it is doing. This declaration declares an explicit specialization for a member of the main template

template<int ALG>
class solve
{
  ...

It has no relation to your explicit specialization

template<>
class solve<IPOPT>
{
  ...

The compiler is trying to specialize constructor solve<ALG>::solve(nlp* problem) of the main template. However, the main template has no such constructor. Hence the error message, that tells you exactly that: the compiler does not understand what constructor you are trying to specialize, it cannot find the matching member in the main template.

For example, you can use this syntax to explicitly specialize the default constructor of the main template

template<>
solve<SQP>::solve()
{
  // Specialized code for `solve<SQP>`'s default constructor
}

This will compile fine since the main template does indeed have such constructor. (Note that you don't have to explicitly specialize the whole class for that, you can just explicitly specialize the constructor.)

Your intent was, obviously, completely different: to provide definition for the constructor in the class template specialization

template<>
class solve<IPOPT>
{
  ...

The proper syntax for that should not mention template<>

solve<IPOPT>::solve(nlp* problem): m_ipopt(problem)
{
}


问:
cron job not running inside docker container on ubuntu
I have a simple Dockerfile as follows

```<code>FROM ubuntu:latest

ADD crontab /etc/cron.d/test-cron

RUN chmod a+x /etc/cron.d/test-cron
RUN touch /var/log/cron.log

CMD cron && tail -f /var/log/cron.log
</code>```

and the content of crontab file is as simple as

```<code>* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
# empty line
</code>```

When I run this on my local OS X machine (with docker-machine running), it works fine ("Hello world" is printed to log file every minute). However, when I try to run it on an Ubuntu machine, the cron job does not run (empty log file).

Here's the command I use to run the container

```<code>docker build -t crontest .
docker run --name cron crontest
</code>```

I am not sure why this would be the case. I wonder if something is wrong with the Ubuntu box that I have (wrong time setting?). I have tried to restart that machine to no effect. I currently do have other docker containers running on the Ubuntu box and they're running fine.

Any suggestion on what I could do to debug/ fix this would be hugely appreciated.

EDIT:

After going inside the container (docker exec -it cron /bin/bash), I can verify that cron is running there:

```<code>root@a2ad451af8d9:/# ps -ef | grep cron
root         1     0  0 20:15 ?        00:00:00 /bin/sh -c cron && tail -f /var/log/cron.log
root         6     1  0 20:15 ?        00:00:00 cron
root         7     1  0 20:15 ?        00:00:00 tail -f /var/log/cron.log
root        25    11  0 20:21 ?        00:00:00 grep --color=auto cron
</code>```

答:
I had similar issue, specifically with Ubuntu 14.04. To debug, I tried running cron in foreground, and found it to emit System error messages while trying to run the scheduled jobs.

Apparently, its a known issue with --net=host parameter (ref: https://github.com/moby/moby/issues/5899). I tried passing --pid=host as suggested, and with that, the cron jobs started running fine.

Body:
I have a simple Dockerfile as follows

FROM ubuntu:latest

ADD crontab /etc/cron.d/test-cron

RUN chmod a+x /etc/cron.d/test-cron
RUN touch /var/log/cron.log

CMD cron && tail -f /var/log/cron.log

and the content of crontab file is as simple as

* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
# empty line

When I run this on my local OS X machine (with docker-machine running), it works fine ("Hello world" is printed to log file every minute). However, when I try to run it on an Ubuntu machine, the cron job does not run (empty log file).

Here's the command I use to run the container

docker build -t crontest .
docker run --name cron crontest

I am not sure why this would be the case. I wonder if something is wrong with the Ubuntu box that I have (wrong time setting?). I have tried to restart that machine to no effect. I currently do have other docker containers running on the Ubuntu box and they're running fine.

Any suggestion on what I could do to debug/ fix this would be hugely appreciated.

EDIT:

After going inside the container (docker exec -it cron /bin/bash), I can verify that cron is running there:

root@a2ad451af8d9:/# ps -ef | grep cron
root         1     0  0 20:15 ?        00:00:00 /bin/sh -c cron && tail -f /var/log/cron.log
root         6     1  0 20:15 ?        00:00:00 cron
root         7     1  0 20:15 ?        00:00:00 tail -f /var/log/cron.log
root        25    11  0 20:21 ?        00:00:00 grep --color=auto cron


问:
Set a default value for UIPickerView in Swift?
How do I set the starting row of the picker view in Swift?

I see there is a similar question for Objective-C, but I don't understand the code.

答:
Default value selected in pickerview in swift 3

If Your array like bellow

```<code>let pickerArray  = [
        ["displayValue":"--Select--" as AnyObject,"id":"" as AnyObject],
        ["displayValue":"Jame" as AnyObject,"id":"100" as AnyObject],
        ["displayValue":"Enamul" as AnyObject,"id":"201" as AnyObject]
    ]
</code>```

Just add bellow line for default selected in pickerview

```<code> pickerViewTextField.text  = pickerArray[0]["displayValue"] as! String
</code>```

ContentLicense: CC BY-SA 4.0

Body:
Default value selected in pickerview in swift 3

If Your array like bellow

let pickerArray  = [
        ["displayValue":"--Select--" as AnyObject,"id":"" as AnyObject],
        ["displayValue":"Jame" as AnyObject,"id":"100" as AnyObject],
        ["displayValue":"Enamul" as AnyObject,"id":"201" as AnyObject]
    ]

Just add bellow line for default selected in pickerview

 pickerViewTextField.text  = pickerArray[0]["displayValue"] as! String


问:
Xamarin Android custom gallery gridview
I'm trying to implement a simple custom gallery to display all photos of my phone using Xamarin.Android.
For that I use a Gridview with an adapter and create thumbnails with

MediaStore.Images.Thumbnails.GetThumbnail

But this method is slow for a big amount of photos, so I've create a Task in order to make it async. Also add CancellationToken on GetView method to cancel multiple same task in parallel.

But something goes wrong and my app crashes without messages or sometimes "outofmemory exeception".

EDITED CODE

Here my Adapter :

```<code>public class ImageAdapter : BaseAdapter
{
    public bool IsScrolling = false;

    private LayoutInflater mInflater;
    private Context mContext;
    private ICursor cursorImage;
    private ViewHolder selectedItem;
    private Bitmap blanckBitmap;

    public ImageAdapter(Context context)
    {
        mInflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
        mContext = context;

        String[] columns = { MediaStore.Images.Media.InterfaceConsts.Id, MediaStore.Images.Media.InterfaceConsts.DateTaken };
        String orderBy = MediaStore.Images.Media.InterfaceConsts.DateTaken + " DESC";

        cursorImage = Application.Context.ContentResolver.Query(
            MediaStore.Images.Media.ExternalContentUri,
            columns,
            null,
            null,
            orderBy);

        blanckBitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb4444);
    }

    public override int Count => cursorImage.Count;

    public override Java.Lang.Object GetItem(int position)
    {
        return position;
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder;
        CancellationTokenSource cts;
        if (convertView == null)
        {
            holder = new ViewHolder();
            convertView = mInflater.Inflate(Resource.Layout.gallery_item, parent, false);
            holder.Imageview = (ImageView)convertView.FindViewById(Resource.Id.gallery_item_thumbImage);
        }
        else
        {
            holder = (ViewHolder)convertView.Tag;
            if (holder != null)
            {
                var wraper = holder.WrapperCancellation.JavaCast<Wrapper<CancellationTokenSource>>();
                wraper?.Data.Cancel();
                holder.WrapperCancellation = wraper;
            }
        }
        holder?.Imageview.SetImageBitmap(blanckBitmap); // Set blanck bitmap

        if (holder != null && !IsScrolling)
        {
            holder.Imageview.Id = position;
            cts = new CancellationTokenSource();
            GetImageThumbnailAsync(holder.Imageview, position, cts.Token);

            holder.WrapperCancellation = new Wrapper<CancellationTokenSource> { Data = cts };

            if (!holder.Imageview.HasOnClickListeners)
            {
                holder.Imageview.Click += (sender, args) =>
                {
                    if (selectedItem != null)
                    {
                        selectedItem.Imageview.CropToPadding = false;
                        selectedItem.Imageview.Background = null;
                    }

                    selectedItem = holder;
                    holder.Imageview.CropToPadding = true;
                    holder.Imageview.Background = mContext.GetDrawable(Resource.Drawable.image_border_selected);
                };
            }
        }
        convertView.Tag = holder;

        return convertView;
    }

    private async Task GetImageThumbnailAsync(ImageView imageView, int imgIndex, CancellationToken ct)
    {
        var bmp = await Task.Run(() =>
        {
            if (ct.IsCancellationRequested)
                return null;

            cursorImage.MoveToPosition(imgIndex);
            var columnIndex = cursorImage.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Id);
            var id = cursorImage.GetInt(columnIndex);

            return MediaStore.Images.Thumbnails.GetThumbnail(
                                                    Application.Context.ContentResolver,
                                                    id,
                                                    ThumbnailKind.MiniKind,
                                                    null);
        }, ct);

        if (!ct.IsCancellationRequested)
        {
            if (bmp != null)
                imageView.SetImageBitmap(bmp);
        }
    }
}
</code>```

The GetImageThumbnailAsync retrieves thumbnail from the GetView position.

And now the ViewHolder class :

```<code>public class ViewHolder : Java.Lang.Object
{
    public ImageView Imageview;
    public int Id;
    public Wrapper<CancellationTokenSource> WrapperCancellation;
}

public class Wrapper<T> : Java.Lang.Object
{
    public T Data;
}
</code>```

And the Scroll event listener :

```<code>imagegrid.ScrollStateChanged += (o, e) =>
        {
            if (e.ScrollState != ScrollState.Idle)
            {
                imageAdapter.IsScrolling = true;
            }
            else
            {
                imageAdapter.IsScrolling = false;
                imageAdapter.NotifyDataSetChanged();
            }
        };
</code>```

答:
It has limited memory for Bitmap in android(about 8M). So if you have too many images loaded, the OOM exception will be thrown.

Besides using the default image to replace the unloaded image temporarily as I suggested in the comment, we also need to cache Bitmaps.

For caching Bitmaps, you can check the official document of Google Android: Use a Disk Cache.

Title: Xamarin Android custom gallery gridview

Body:
I'm trying to implement a simple custom gallery to display all photos of my phone using Xamarin.Android.
For that I use a Gridview with an adapter and create thumbnails with

MediaStore.Images.Thumbnails.GetThumbnail

But this method is slow for a big amount of photos, so I've create a Task in order to make it async. Also add CancellationToken on GetView method to cancel multiple same task in parallel.

But something goes wrong and my app crashes without messages or sometimes "outofmemory exeception".

EDITED CODE

Here my Adapter :

public class ImageAdapter : BaseAdapter
{
    public bool IsScrolling = false;

    private LayoutInflater mInflater;
    private Context mContext;
    private ICursor cursorImage;
    private ViewHolder selectedItem;
    private Bitmap blanckBitmap;

    public ImageAdapter(Context context)
    {
        mInflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
        mContext = context;

        String[] columns = { MediaStore.Images.Media.InterfaceConsts.Id, MediaStore.Images.Media.InterfaceConsts.DateTaken };
        String orderBy = MediaStore.Images.Media.InterfaceConsts.DateTaken + " DESC";

        cursorImage = Application.Context.ContentResolver.Query(
            MediaStore.Images.Media.ExternalContentUri,
            columns,
            null,
            null,
            orderBy);

        blanckBitmap = Bitmap.CreateBitmap(100, 100, Bitmap.Config.Argb4444);
    }

    public override int Count => cursorImage.Count;

    public override Java.Lang.Object GetItem(int position)
    {
        return position;
    }

    public override long GetItemId(int position)
    {
        return position;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        ViewHolder holder;
        CancellationTokenSource cts;
        if (convertView == null)
        {
            holder = new ViewHolder();
            convertView = mInflater.Inflate(Resource.Layout.gallery_item, parent, false);
            holder.Imageview = (ImageView)convertView.FindViewById(Resource.Id.gallery_item_thumbImage);
        }
        else
        {
            holder = (ViewHolder)convertView.Tag;
            if (holder != null)
            {
                var wraper = holder.WrapperCancellation.JavaCast<Wrapper<CancellationTokenSource>>();
                wraper?.Data.Cancel();
                holder.WrapperCancellation = wraper;
            }
        }
        holder?.Imageview.SetImageBitmap(blanckBitmap); // Set blanck bitmap

        if (holder != null && !IsScrolling)
        {
            holder.Imageview.Id = position;
            cts = new CancellationTokenSource();
            GetImageThumbnailAsync(holder.Imageview, position, cts.Token);

            holder.WrapperCancellation = new Wrapper<CancellationTokenSource> { Data = cts };

            if (!holder.Imageview.HasOnClickListeners)
            {
                holder.Imageview.Click += (sender, args) =>
                {
                    if (selectedItem != null)
                    {
                        selectedItem.Imageview.CropToPadding = false;
                        selectedItem.Imageview.Background = null;
                    }

                    selectedItem = holder;
                    holder.Imageview.CropToPadding = true;
                    holder.Imageview.Background = mContext.GetDrawable(Resource.Drawable.image_border_selected);
                };
            }
        }
        convertView.Tag = holder;

        return convertView;
    }

    private async Task GetImageThumbnailAsync(ImageView imageView, int imgIndex, CancellationToken ct)
    {
        var bmp = await Task.Run(() =>
        {
            if (ct.IsCancellationRequested)
                return null;

            cursorImage.MoveToPosition(imgIndex);
            var columnIndex = cursorImage.GetColumnIndex(MediaStore.Images.Media.InterfaceConsts.Id);
            var id = cursorImage.GetInt(columnIndex);

            return MediaStore.Images.Thumbnails.GetThumbnail(
                                                    Application.Context.ContentResolver,
                                                    id,
                                                    ThumbnailKind.MiniKind,
                                                    null);
        }, ct);

        if (!ct.IsCancellationRequested)
        {
            if (bmp != null)
                imageView.SetImageBitmap(bmp);
        }
    }
}

The GetImageThumbnailAsync retrieves thumbnail from the GetView position.

And now the ViewHolder class :

public class ViewHolder : Java.Lang.Object
{
    public ImageView Imageview;
    public int Id;
    public Wrapper<CancellationTokenSource> WrapperCancellation;
}

public class Wrapper<T> : Java.Lang.Object
{
    public T Data;
}

And the Scroll event listener :

imagegrid.ScrollStateChanged += (o, e) =>
        {
            if (e.ScrollState != ScrollState.Idle)
            {
                imageAdapter.IsScrolling = true;
            }
            else
            {
                imageAdapter.IsScrolling = false;
                imageAdapter.NotifyDataSetChanged();
            }
        };


问:
Index out of range error in Swift 3
I know there are plenty questions about that problem in SO, but i've found nothing useful for me.

I'm doing an app able to recognize movement on the screen. But Apple gestures recognizers are too precise for my use, so I'm doing my own.

It's almost done and working.

I'd like to handle multitouch gesture (like pinch) and I need to get the direction of each finger on the screen, for this I was thinking to include each direction in an array so i'll compare them easily after. But I'm getting that error of index out of range, and I don't know where I'm wrong. I'm pretty new to swift (self learning since 1 month) so it can be obvious or even a stupid mistake...

If you could please help me on this, I'd be glad.
Thanks !

Here is my full code :

```<code>import UIKit

class ViewController: UIViewController {
//@IBOutlet weak var statusLabel: UILabel!

@IBOutlet weak var StatusLabel: UILabel!

var fingers = [String?](repeating: nil, count:10)
var finger1 = [CGFloat]()
var finger2 = [CGFloat]()
var finger3 = [CGFloat]()
var finger4 = [CGFloat]()
var finger5 = [CGFloat]()
var direction: String = ""
var direction1 = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        direction = ""
        direction1 = []
        finger1 = []
        finger2 = []
        finger3 = []
        finger4 = []
        finger5 = []
        for touch in touches{
            let point = touch.location(in: self.view)
            for (index,finger)  in fingers.enumerated() {
                if finger == nil {
                    fingers[index] = String(format: "%p", touch)
                    print("finger \(index+1): x=\(point.x) , y=\(point.y)")
                    break
                }
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        for touch in touches {
            let point = touch.location(in: self.view)
            for (index,finger) in fingers.enumerated() {
                if let finger = finger, finger == String(format: "%p", touch) {
                    switch (index){
                    case 0 :
                        finger1 += [point.x, point.y]
                    case 1 :
                        finger2 += [point.x, point.y]
                    case 2 :
                        finger3 += [point.x, point.y]
                    case 3 :
                        finger4 += [point.x, point.y]
                    case 4 :
                        finger5 += [point.x, point.y]
                    default :
                        break
                    }
                }
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        for touch in touches {
            for (index,finger) in fingers.enumerated() {
                if let finger = finger, finger == String(format: "%p", touch) {
                    fingers[index] = nil
                    break
                }
            }
        }
        if finger1.count != 0 {
            direction1[0] += GestureRecognizer(coordinates: finger1, index: 0)
        }
        if finger2.count != 0 {
            direction1[1] += GestureRecognizer(coordinates: finger2, index: 1)
        }
        if finger3.count != 0 {
            direction1[2] += GestureRecognizer(coordinates: finger3, index: 2)
        }
        if finger4.count != 0 {
            direction1[3] += GestureRecognizer(coordinates: finger4, index: 3)
        }
        if finger5.count != 0 {
            direction1[4] += GestureRecognizer(coordinates: finger5, index: 4)
        }

        print("1 " + direction1[0] + "2 " + direction1[1] + "3 " + direction1[2] + "4 " + direction1[3] + "5 " + direction1[4])
        StatusLabel.text = direction1[1]
    }

    func GestureRecognizer (coordinates: [CGFloat], index: Int) -> String {
        if (coordinates[0] - coordinates[coordinates.count-2]) > 100 && (coordinates[1] - coordinates[coordinates.count-1]) < (-100) {
            print("Vers la gauche et bas")
            direction1[0] = "downleft"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) < (-100) && (coordinates[1] - coordinates[coordinates.count-1]) > 100{
            print("Vers la droite et haut")
            direction1[index] = "upright"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) < (-100 ) && (coordinates[1] - coordinates[coordinates.count-1]) < (-100){
            print("Vers la droite et bas")
            direction1[index] = "downright"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) > 100 &&  (coordinates[1] - coordinates[coordinates.count-1]) > 100 {
            print("Vers la gauche et haut")
            direction1[index] = "upleft"
        }
        else if (-100..<100).contains(coordinates[0] - coordinates[coordinates.count-2]) && (coordinates[1] - coordinates[coordinates.count-1]) > 100 {
            print("Swipe up")
            direction1[index] = "swipeup"
        }
        else if (-100..<100).contains(coordinates[0] - coordinates[coordinates.count-2]) && (coordinates[1] - coordinates[coordinates.count-1]) < -100 {
            print("Swipe Down")
            direction1[index] = "swipedown"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) > 100 && (-100..<100).contains(coordinates[1] - coordinates[coordinates.count-1]){
            print("Swipe left")
            direction1[index] = "swipeleft"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) < -100 && (-100..<100).contains(coordinates[1] - coordinates[coordinates.count-1]){
            print("Swipe right")
            direction1[index] = "swiperight"
        }
        else {
            direction1[index] = "failed"
        }
        return direction1[index]
    }
}
</code>```

答:
You should recheck your direction1 array. The error is likely to be in this line:

```<code>print("1 " + direction1[0] + "2 " + direction1[1] + "3 " + direction1[2] + "4 " + direction1[3] + "5 " + direction1[4])
</code>```

You've set direction1 = [] and then you tried to print 5 different elements in your direction1 array.

Workaround is to initialise a fixed-size array [String](repeating: "", count: 5) and remove this line direction1 = []

Title: Index out of range error in Swift 3

Body:
I know there are plenty questions about that problem in SO, but i've found nothing useful for me.

I'm doing an app able to recognize movement on the screen. But Apple gestures recognizers are too precise for my use, so I'm doing my own.

It's almost done and working.

I'd like to handle multitouch gesture (like pinch) and I need to get the direction of each finger on the screen, for this I was thinking to include each direction in an array so i'll compare them easily after. But I'm getting that error of index out of range, and I don't know where I'm wrong. I'm pretty new to swift (self learning since 1 month) so it can be obvious or even a stupid mistake...

If you could please help me on this, I'd be glad.
Thanks !

Here is my full code :

import UIKit

class ViewController: UIViewController {
//@IBOutlet weak var statusLabel: UILabel!

@IBOutlet weak var StatusLabel: UILabel!

var fingers = [String?](repeating: nil, count:10)
var finger1 = [CGFloat]()
var finger2 = [CGFloat]()
var finger3 = [CGFloat]()
var finger4 = [CGFloat]()
var finger5 = [CGFloat]()
var direction: String = ""
var direction1 = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        direction = ""
        direction1 = []
        finger1 = []
        finger2 = []
        finger3 = []
        finger4 = []
        finger5 = []
        for touch in touches{
            let point = touch.location(in: self.view)
            for (index,finger)  in fingers.enumerated() {
                if finger == nil {
                    fingers[index] = String(format: "%p", touch)
                    print("finger \(index+1): x=\(point.x) , y=\(point.y)")
                    break
                }
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        for touch in touches {
            let point = touch.location(in: self.view)
            for (index,finger) in fingers.enumerated() {
                if let finger = finger, finger == String(format: "%p", touch) {
                    switch (index){
                    case 0 :
                        finger1 += [point.x, point.y]
                    case 1 :
                        finger2 += [point.x, point.y]
                    case 2 :
                        finger3 += [point.x, point.y]
                    case 3 :
                        finger4 += [point.x, point.y]
                    case 4 :
                        finger5 += [point.x, point.y]
                    default :
                        break
                    }
                }
            }
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        for touch in touches {
            for (index,finger) in fingers.enumerated() {
                if let finger = finger, finger == String(format: "%p", touch) {
                    fingers[index] = nil
                    break
                }
            }
        }
        if finger1.count != 0 {
            direction1[0] += GestureRecognizer(coordinates: finger1, index: 0)
        }
        if finger2.count != 0 {
            direction1[1] += GestureRecognizer(coordinates: finger2, index: 1)
        }
        if finger3.count != 0 {
            direction1[2] += GestureRecognizer(coordinates: finger3, index: 2)
        }
        if finger4.count != 0 {
            direction1[3] += GestureRecognizer(coordinates: finger4, index: 3)
        }
        if finger5.count != 0 {
            direction1[4] += GestureRecognizer(coordinates: finger5, index: 4)
        }

        print("1 " + direction1[0] + "2 " + direction1[1] + "3 " + direction1[2] + "4 " + direction1[3] + "5 " + direction1[4])
        StatusLabel.text = direction1[1]
    }

    func GestureRecognizer (coordinates: [CGFloat], index: Int) -> String {
        if (coordinates[0] - coordinates[coordinates.count-2]) > 100 && (coordinates[1] - coordinates[coordinates.count-1]) < (-100) {
            print("Vers la gauche et bas")
            direction1[0] = "downleft"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) < (-100) && (coordinates[1] - coordinates[coordinates.count-1]) > 100{
            print("Vers la droite et haut")
            direction1[index] = "upright"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) < (-100 ) && (coordinates[1] - coordinates[coordinates.count-1]) < (-100){
            print("Vers la droite et bas")
            direction1[index] = "downright"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) > 100 &&  (coordinates[1] - coordinates[coordinates.count-1]) > 100 {
            print("Vers la gauche et haut")
            direction1[index] = "upleft"
        }
        else if (-100..<100).contains(coordinates[0] - coordinates[coordinates.count-2]) && (coordinates[1] - coordinates[coordinates.count-1]) > 100 {
            print("Swipe up")
            direction1[index] = "swipeup"
        }
        else if (-100..<100).contains(coordinates[0] - coordinates[coordinates.count-2]) && (coordinates[1] - coordinates[coordinates.count-1]) < -100 {
            print("Swipe Down")
            direction1[index] = "swipedown"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) > 100 && (-100..<100).contains(coordinates[1] - coordinates[coordinates.count-1]){
            print("Swipe left")
            direction1[index] = "swipeleft"
        }
        else if (coordinates[0] - coordinates[coordinates.count-2]) < -100 && (-100..<100).contains(coordinates[1] - coordinates[coordinates.count-1]){
            print("Swipe right")
            direction1[index] = "swiperight"
        }
        else {
            direction1[index] = "failed"
        }
        return direction1[index]
    }
}

Body:
You should recheck your direction1 array. The error is likely to be in this line:

print("1 " + direction1[0] + "2 " + direction1[1] + "3 " + direction1[2] + "4 " + direction1[3] + "5 " + direction1[4])

You've set direction1 = [] and then you tried to print 5 different elements in your direction1 array.

Workaround is to initialise a fixed-size array [String](repeating: "", count: 5) and remove this line direction1 = []