C# GetAsyncDataFromWeb

C#/통신 2016. 8. 21. 23:36
728x90

HttpWebRequest 방식으로는 데이터를 가져오는 크기에 한도가 있는 거 같다.

아래 방식으로 하면 데이터를 많이 가져온다.


// GET 방식으로 Web 에 있는 데이터를 가져온다.

void GetAsyncDataFromWeb(string url)
{
    var client = new HttpClient();
    var response = client.GetAsync(url).Result;
    string resultContent = response.Content.ReadAsStringAsync().Result;
}



// POST 방식으로 Web 에 있는 데이터를 가져온다.

void GetAsyncDataFromWeb(string url)
{
    var client = new HttpClient();
    var postData = new List<KeyValuePair<string, string>>();
    postData.Add(new KeyValuePair<string, string>("UserName", "Grace"));
    postData.Add(new KeyValuePair<string, string>("userID ", "12345"));
    var formContent = new FormUrlEncodedContent(postData);

    var response = client.PostAsync(url, formContent).Result;
    string resultContent = response.Content.ReadAsStringAsync().Result;
}


postData 값을 넘기는 방법은 여러가지가 있다.

http://stackoverflow.com/questions/3001108/namevaluecollection-vs-dictionarystring-string

에 Dictionary<string,string> 와 NameValueCollection 차이점에 대한 문의 내용인데 간략한 답변이 나온다.

블로그 이미지

Link2Me

,
728x90

스승도 없이 독학으로 취미로 프로그램을 배우다보니 막히면 중단되고 방법을 찾으면 약간 진도가 나간다.

배우면서 느끼는 것은 기본기가 중요하다는 점이다.

기능 검색하다가 우연히 http://raago.tistory.com/20 에서 함수명을 직관적으로 이해되게 작성하는 것이 정말 중요하다는 걸 새삼 느꼈다.

앞으로는 자료 검색을 하더라도 허투루 보지 않고 응용해서 내것으로 만들어야겠다.


자료 검색을 하면 대부분 POST 처리 부분이 좀 부족하게 검색된다.

POST 데이터 입력부분까지 고려해서 만들었다.

서버에서 던져주는 결과를 가져오는 함수니까 GetDataFromWeb 으로 하면 맞다.

결과 형식이 JSON이면 Deserialize 하는 것은 별도로 처리해야 한다.


string GetJDataFromWeb(string url, string postData)
 {
     try
     {
         var webRequest = (HttpWebRequest)WebRequest.Create(url);

         if (postData != null)
         {
             webRequest.Method = "POST";
             byte[] sendData = UTF8Encoding.UTF8.GetBytes(postData);
             webRequest.ContentType = "application/x-www-form-urlencoded";
             webRequest.ContentLength = sendData.Length;

             Stream dataStream = webRequest.GetRequestStream();
             dataStream.Write(sendData, 0, sendData.Length);
             dataStream.Close();
         }

         var webResponse = (HttpWebResponse)webRequest.GetResponse();
         if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
         {
             var readStrem = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8, true);

             string reader = readStream.ReadToEnd().Trim();

             readStrem.Close();

             webResponse.Close();

             return @reader.ReadToEnd().Trim();
         }
         else
         {
             MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));
             return null;
         }
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message);
         return null;
     }
 }


파일을 첨부하는 경우는 테스트를 못해봤지만, 파일 첨부한 경우에는 별도 함수를 만들어야 할 것으로 예상된다.


가져온 데이터 형식이 JSON String 인 경우 이 문자열을 Deserialize 하는 함수 부분은

string URL = "http://IPaddress/cat1comboBox.php";
string json = GetJSONFromWeb(URL, null);
if (json != null)
{
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    // Json String 를 객체로 반환 (역직렬화)
    JsonHelper category1 = serializer.Deserialize<JsonHelper>(json);

    datagGridView1 에 연결하거나, comboBox 에 연결 처리 추가하면 된다.
}


구글링 결과가 대부분 외국 자료이다보니 영문 중심이라 한글을 제대로 보여주지 못한다.

JavaScriptSerializer serializer = new JavaScriptSerializer(); 는 한글을 제대로 표현해준다.


코드를 구현해서 실제 적용을 해보니 데이터를 많이 가져올 수 없다. ㅠㅠㅠ

블로그 이미지

Link2Me

,
728x90

C# comboBox 에서 POST 방식으로 서버에 값을 전달하고 서버에서 그 결과를 회신하는 코드에 대해 작성한다.


private void cat1comboBox1_SelectedIndexChanged_1(object sender, EventArgs e)
{
    if (cat1comboBox1.SelectedIndex > 0)
    {
        cat1name1 = ((KeyValuePair<string, string>)cat1comboBox1.SelectedItem).Key;
        cat1uid1 = ((KeyValuePair<string, string>)cat1comboBox1.SelectedItem).Value;
        cat2comboBox(cat1uid1, cat2comboBox1); // 두번째 comboBox 표시
    }
}

void cat2comboBox(string category1, ComboBox CB)
{
    Dictionary<string, string> cat2Source = new Dictionary<string, string>();
    cat2Source.Add("전체", "0");
    try
    {
        string URL = "http://IP주소/cat2comboBox.php";
        string json = POSTPHPJSON(URL, category1);
        if (json != null)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            JsonHelper2 category2 = serializer.Deserialize<JsonHelper2>(json);

            foreach (var dr in category2.result)
            {
                cat2Source.Add(dr.classname, dr.uid);
            }

            CB.DataSource = new BindingSource(cat2Source, null);
            CB.DisplayMember = "Key";
            CB.ValueMember = "Value";

            CB.SelectedIndex = 0;  // 첫번째 아이템 선택
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }

}

private void cat2comboBox1_SelectedIndexChanged_1(object sender, EventArgs e)
{
    if (cat2comboBox1.SelectedIndex > 0)
    {
        cat2name1 = ((KeyValuePair<string, string>)cat2comboBox1.SelectedItem).Key;
        cat2uid1 = ((KeyValuePair<string, string>)cat2comboBox1.SelectedItem).Value;
        MessageBox.Show(cat2name1 + " : " + cat2uid1);
    }
}

string POSTPHPJSON(string url, string Data)
{
    try
    {
        var webRequest = (HttpWebRequest)WebRequest.Create(url);
        var postData = string.Format("catagory1={0}", Data); 

        // 좀 더 정교한 함수로 처리하려면 이 부분은 함수 밖에서 처리하는게 좋다.

        webRequest.Method = "POST";
        byte[] sendData = UTF8Encoding.UTF8.GetBytes(postData);
        webRequest.ContentType = "application/x-www-form-urlencoded";
        webRequest.ContentLength = sendData.Length;

        Stream dataStream = webRequest.GetRequestStream();
        dataStream.Write(sendData, 0, sendData.Length);
        dataStream.Close();

        var webResponse = (HttpWebResponse)webRequest.GetResponse();
        if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
        {
            var reader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8, true);
            return @reader.ReadToEnd().Trim();
        }
        else
        {
            MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));
            return null;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }
}

public class cat2comboBox
{
    public string uid { get; set; }
    public string classname { get; set; }
}

public class JsonHelper2
{
    public List<cat2comboBox> result { get; set; }
}


블로그 이미지

Link2Me

,
728x90

C# comboBox 에 DB 테이블 정보를 가져와서 List Up 하는 방법이다.


MySQL DB를 직접 접속하는 방식이 아니라, Web 서버 정보를 JSON 으로 파싱해서 연동하는 방법이다.

기본 사항은 http://net-informations.com/q/faq/combovalue.html http://stackoverflow.com/questions/3063320/combobox-adding-text-and-value-to-an-item-no-binding-source 참조하면 도움된다.


코드는 일반적인 형태와 약간 다르게 처리할 수 밖에 없었다.

일반적인 경우에는 CB.DataSource = new BindingSource(cat1Source, null); 대신에 CB.DataSource = category1.result; 로 하면 된다.

하지만 이렇게 하면 전체 라는 구분자가 보이지 않는다.

그래서 별도로 Dictionary 를 이용해서 저장한 다음에 다시 매핑을 시켰다.

서버 파일을 변경하여 연동 에러가 발생하게 하여 미처 고려하지 못한 버그도 수정 반영하였다.

화면에 보이는 Text 만 고려하지 않고 value 까지 고려한 이유는 comboBox 아이템을 선택했을 때 uid 를 이용하여 DB 테이블 조회를 하기 위해서다.


using System;
using System.Web;
using System.Web.Script.Serialization;
using System.Net;
using System.Windows.Forms;
using System.Collections.Generic;
using System.IO;
using System.Data;
using System.Text;

private void Form1_Load(object sender, EventArgs e)
{
    cat1comboBox(cat1comboBox1); // DB 테이블 정보 가져오기
}

void cat1comboBox(ComboBox CB)
{
    CB.Items.Clear();
    Dictionary<string, string> cat1Source = new Dictionary<string, string>();
    cat1Source.Add("전체", "0");  // DB에는 전체가 없어서 추가
    try
    {
        string URL = "http://IP주소/cat1comboBox.php";
        string json = GetPHPJSON(URL);
        if (json != null)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            JsonHelper category1 = serializer.Deserialize<JsonHelper>(json); // Json String 객체로 반환 (역직렬화)

            foreach (var dr in category1.result)
            {
                cat1Source.Add(dr.classname, dr.uid);
            }

            CB.DataSource = new BindingSource(cat1Source, null);
            CB.DisplayMember = "Key";
            CB.ValueMember = "Value";

            CB.SelectedIndex = 0;  // 첫번째 아이템 선택
        }               
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
   
}

private void cat1comboBox1_SelectedIndexChanged_1(object sender, EventArgs e)
{
    if (cat1comboBox1.SelectedIndex > 0)
    {
        string key = ((KeyValuePair<string, string>)cat1comboBox1.SelectedItem).Key;
        string value = ((KeyValuePair<string, string>)cat1comboBox1.SelectedItem).Value;
        MessageBox.Show(key + " : " + value);
    }
}

string GetPHPJSON(string url)
{
    try
    {
        var webRequest = (HttpWebRequest)WebRequest.Create(url);
        var webResponse = (HttpWebResponse)webRequest.GetResponse();
        if ((webResponse.StatusCode == HttpStatusCode.OK) && (webResponse.ContentLength > 0))
        {
            var reader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8, true);
            return @reader.ReadToEnd().Trim();
        }
        else
        {
            MessageBox.Show(string.Format("Status code == {0}", webResponse.StatusCode));
            return null;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return null;
    }
}


public class cat1comboBox
{
    public string uid { get; set; }
    public string classname { get; set; }      
}

public class JsonHelper
{
    public List<cat1comboBox> result { get; set; }
}

블로그 이미지

Link2Me

,
728x90

PHP 서버에서 가져온 데이터 형식이라고 가정한다.

Local 에서 JSON 형식으로 데이터를 만들 이유는 없을 것이다.


public static string DeserializeNames()
{
    jsonData = "{\"name\":[{\"last\":\"Smith\"},{\"last\":\"Doe\"}]}";
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    JsonHelper myNames = serializer.Deserialize<JsonHelper>(jsonData);
    return ser.Serialize(myNames);
}

//Class descriptions
public class name
{
   public string last { get; set; }
}

public class JsonHelper
{
   public List<name> { get; set; }
}



두개는 같이 사용 가능하다.

List<name> myNames = ser.Deserialize<List<name>>(jsonData);
JsonHelper myNames = ser.Deserialize<JsonHelper>(jsonData);


PHP 서버에서 JSON 을 가져오는 소스코드는

string GetJSONFromPHP(string url)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    try
    {
        WebResponse response = request.GetResponse();
        using (Stream responseStream = response.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, Encoding.UTF8, true);
            return @reader.ReadToEnd().Trim();
        }
    }
    catch (WebException ex)
    {
        WebResponse errorResponse = ex.Response;
        using (Stream responseStream = errorResponse.GetResponseStream())
        {
            StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
        }
        throw;
    }
}



jsonData = "{\"name\":[{\"last\":\"Smith\"},{\"last\":\"Doe\"}]}"; 대신에


using System.Web.Script.Serialization;
jsonData = GetJSONFromPHP(string url); 를 사용하면 된다.


dataGridView1 에다가 연결하는 방법은

JavaScriptSerializer serializer = new JavaScriptSerializer();
JsonHelper myNames = serializer.Deserialize<JsonHelper>(json);
dataGridView1.DataSource = myNames.name;


또는

JavaScriptSerializer serializer = new JavaScriptSerializer();
List<name> myNames = ser.Deserialize<List<name>>(jsonData);
dataGridView1.DataSource = myNames.ToArray();


로 하면 된다.    



블로그 이미지

Link2Me

,
728x90

C# Layout 에서 기존 자료를 복사하여 사용하다보니 아주 사소한 곳에서 에러가 발생한다.


Tabpage 를 추가하고 SplitContainer 로 화면을 분할한 후에

기존 Tabpage 에 있는 comboBox 를 복사하여 붙여넣기를 했다.

파일 이름을 먼저 변경하지 않고 작업하다보니 꼬이는 부분이 발생한다.

꼬이면 해당 부분을 잠시 주석처리를 했다가 다시 원복하면 정상으로 변경되더라.


datagridView 배경색을 변경하여 색상이 튀지 않도록 해준다.




DB에서 가져온 칼럼 이름이 없으면 에러가 발생한다.


칼럼 이름을 정확하게 적어줘야 에러가 없어진다.

특히 select 문에 case 를 이용하여 값이 표기되도록 할 때 별칭 칼럼을 잘못 적어서 에러가 발생했는데, 오랫만에 하니까 또 같은 부분에서 에러가 났다.



블로그 이미지

Link2Me

,
728x90

Web 사이트에 C#에서 보내는 값을 저장하는 예제이다.

form 에서 보내는 데이터처럼 데이터를 보내는 식으로 값을 전달하면 저장된다.

테스트를 위해서 작성해본 것이라서 소스 내용이 정교하지는 못하다.

PostData 값을 전달하는 부분만 수정해서 사용하기 위해 작성해둔다.


private void btnSave_Click(object sender, EventArgs e)
{
    if (cat1name.Text.Trim() == "")
    {
        MessageBox.Show("카테고리1을 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.cat1name.Focus();
    }
    else if (cat2name.Text.Trim() == "")
    {
        MessageBox.Show("카테고리2을 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.cat2name.Focus();
    }
    else if (textBox1.Text.Trim() == "")
    {
        MessageBox.Show("이름을 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.textBox1.Focus();
    }
    else if (mobile1.Text.Trim() == "")
    {
        MessageBox.Show("휴대폰번호 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.mobile1.Focus();
    }
    else if (mobile2.Text.Trim() == "")
    {
        MessageBox.Show("휴대폰번호 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.mobile2.Focus();
    }
    else if (mobile3.Text.Trim() == "")
    {
        MessageBox.Show("휴대폰번호 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.mobile3.Focus();
    }
    else
    {
        NameValueCollection strqry = new NameValueCollection();
        strqry.Add("uid", uid.Text.Trim());
        strqry.Add("category1", cat1name.Text.Trim());
        strqry.Add("category2", cat2name.Text.Trim());
        strqry.Add("name", textBox1.Text.Trim());
        strqry.Add("email", textBox2.Text.Trim());
        strqry.Add("mobile_1", mobile1.Text.Trim());
        strqry.Add("mobile_2", mobile2.Text.Trim());
        strqry.Add("mobile_3", mobile3.Text.Trim());

        Address_DBSave(strqry);
    }           
}

private string Address_DBSave(NameValueCollection strqry)
{
    // 주소록 DB에 저장하는 메소드
    string url = "http://www.abc.com/";
    // PostData 코드 부분
    string boundary = "-----------------------------267631966917210";
    string end_boundary = "-----------------------------267631966917210--\r\n";

    StringBuilder sb = new StringBuilder();
    foreach (string fieldName in strqry.Keys)
    {
        string fieldValue = strqry.Get(fieldName);
        sb.AppendFormat("{0}\r\n" + "Content-Disposition: form-data; name={1}\r\n\r\n{2}\r\n", boundary, fieldName, fieldValue);
    }
    sb.Append(end_boundary);
    string PostData = sb.ToString();

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";
    byte[] sendData = UTF8Encoding.UTF8.GetBytes(PostData);
    // Web Header 분석기에서 구한 POST 정보를 여기에 적는다

    Stream dataStream = request.GetRequestStream();
    dataStream.Write(sendData, 0, sendData.Length);
    dataStream.Close();

    string resResult = string.Empty;
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    StreamReader readerPost = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8, true);
    resResult = readerPost.ReadToEnd();
    readerPost.Close();
    response.Close();
    //MessageBox.Show(resResult);

    if (resResult.IndexOf("등록") != -1)
    {
        MessageBox.Show("등록되었습니다");
    }
    return null;
}


블로그 이미지

Link2Me

,
728x90

NameValueCollectionkey와 value를 모두 string으로 받아 보관하는 Collection이다. 

NameValueCollection strqry = new NameValueCollection()
{
  {"key1", "value1"},
  {"key2", "value2"},
  {"key3", "value3"}
};

아래 코드는 같은 결과를 3가지 경우로 보여주도록 처리된 예제를 만들었다.
상황에 따라 활용할 수 있게 하기 위해서다.

using System.Collections.Specialized; // NameValueCollection
private void btnSave_Click(object sender, EventArgs e)
{
NameValueCollection strqry = new NameValueCollection();
strqry.Add("Very High", "80");
strqry.Add("High", "60");
strqry.Add("medium", "50");
strqry.Add("Pass", "40");

foreach (string fieldName in strqry.Keys)
{
foreach (string fieldValue in strqry.GetValues(fieldName))
{
MessageBox.Show(fieldName + " - " + fieldValue);
}
}

foreach (string fieldName in strqry.Keys)
{
string fieldValue = strqry.Get(fieldName);
MessageBox.Show(fieldName + " - " + fieldValue);
}

for (int i = 0; i < strqry.Count; i++)
{
MessageBox.Show(i.ToString() + " : " + strqry.GetKey(i) + " - " + strqry.Get(i));
}
}

참고하면 도움될 사이트
http://www.c-sharpcorner.com/UploadFile/d3e4b1/practical-usage-of-namevaluecollection-in-C-Sharp-part1/



 


'C# > 문법 및 기능' 카테고리의 다른 글

C# 접근 제한자(Access Modifier)  (0) 2019.08.13
자바와 C#의 차이점  (0) 2016.12.27
C# Dictionary 와 comboBox 연결  (0) 2016.02.08
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
C# 시간 메소드  (0) 2016.01.15
블로그 이미지

Link2Me

,
728x90

Web 사이트에서 로그인 처리를 C#에서 처리하는 방법을 간단하게 적어둔다.

로그인 버튼을 누르면 아이디와 패스워드 입력 값이 있는지 없는지 체크를 한다.


private void btnOK_Click(object sender, EventArgs e)
{
    if (this.txtID.Text == "")
    {
        MessageBox.Show("로그인 아이디를 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.txtID.Focus();
    }
    else if (this.txtPwd.Text == "")
    {
        MessageBox.Show("로그인 비밀번호를 입력하세요", "알림", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        this.txtPwd.Focus();
    }
    else
    {
        strSessionID = doLogin(txtID.Text, txtPwd.Text);
        if (strSessionID.Length > 0)
        {
            this.Close();
        }
    }
}


이제 실제 로그인 검사를 하는 doLogin(string ID, string PW) 함수를 만들어야 한다.

using System.Net;
using System.IO;

MessageBox.Show(resResult);  부분은 메시지 확인이 다 끝났으면 주석처리를 한다.

resResult.IndexOf 메소드를 이용하여 메시지에서 키워드를 추출하여 포함여부를 체크하여 로그인의 정상/비정상 메시지를 확인할 수 있게 한다.

Web Header 정보는 HTTP Analyzer V7 을 이용해서 확인할 수 있다.

로그인 함수는 만들기 나름이다.

postData 정보인 userID, userPW 정보를 보내서 받은 결과값(화면에 뿌리는 결과, PHP 에서는 echo 결과) 을 가지고 원하는 정보를 파싱해서 로그인 처리를 하게 된다.

만들기에 따라서는 간단하게 코드화를 해서 코드값만 결과로 받아서 처리할 수도 있다.


쿠키정보 값을 알아내려면

string cookie = webResponse.GetResponseHeader("Set-Cookie");
MessageBox.Show(cookie);
를 이용해서 쿠기값을 확인해볼 수가 있다.

그런 다음에 원하는 세션 정보만 추출해서 저장한다.


private string doLogin(string ID, string PW)
{
    string url = "http://www.abc.com/";
    // Web Header 분석기에서 구한 PostData 정보를 여기에 적는다
    string PostData = string.Format("r=home&a=login&id={0}&pw={1}", ID.Trim(), PW.Trim());


    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
    byte[] sendData = UTF8Encoding.UTF8.GetBytes(PostData);
    webRequest.Method = "POST";
    webRequest.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)";
    webRequest.ContentType = "application/x-www-form-urlencoded";
    webRequest.KeepAlive = true;
    webRequest.AllowAutoRedirect = false;

    Stream dataStrem = webRequest.GetRequestStream();
    dataStrem.Write(sendData, 0, sendData.Length);
    dataStrem.Close();

    HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
    StreamReader readStream = new StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.UTF8, true);
    string resResult = readStream.ReadToEnd().Trim();
    MessageBox.Show(resResult);  // 패스워드 정상 / 비정상 메시지를 확인한다.
    readStream.Close();
    webResponse.Close();

    CK = false;
    if(resResult.IndexOf("history.go(-1);//]]>") < 0)  // 웹페이지 메세지가 없으면
    {
        if (webResponse.GetResponseHeader("Set-Cookie").IndexOf("PHPSESSID=") != -1)
        {
            CK = true;
            strSessionID = SSplit(SSplit(webResponse.GetResponseHeader("Set-Cookie"), "PHPSESSID=", 1), ";", 0);
            strID = txtID.Text;
        }
        else
        {
            strID = string.Empty;
        }
    }
    else
    {
        strID = string.Empty;
    }
    return strID;
}


public static string SSplit(string _body, string _parseString, int index)
{
    string varTemp = _body.Split(new string[] { _parseString }, StringSplitOptions.None)[index];
    return varTemp;
}


블로그 이미지

Link2Me

,
728x90

Key_Down 이벤트에 아래와 같이 코드를 추가해주면 엔터키를 쳤을 때 다음 행으로 이동이 안된다.

구글에서 c# datagridview cell enter event 로 검색하면 관련 게시글들이 나온다.


private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyData == Keys.Enter)
    {
        int column = dataGridView1.CurrentCell.ColumnIndex;
        int row = dataGridView1.CurrentCell.RowIndex;
        dataGridView1.CurrentCell = dataGridView1[column, row];
        e.Handled = true;
    }
}


엔터키를 치면 행으로 이동하지 않고 칼럼으로 이동하고 마지막 칼럼에서는 다음행의 첫번째 칼럼으로 이동하게 하는 코드

private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyData == Keys.Enter)
    {
        e.SuppressKeyPress = true;
        int column = dataGridView1.CurrentCell.ColumnIndex;
        int row = dataGridView1.CurrentCell.RowIndex;
        if (column == dataGridView1.Columns.Count -1)
        {
            dataGridView1.CurrentCell = dataGridView1[0, row + 1];
        }
        else
        {
            dataGridView1.CurrentCell = dataGridView1[column + 1, row];
        }
    }
}

블로그 이미지

Link2Me

,
728x90

C# Dictionary 와 콤보박스 연결해서 값을 알아내는 걸 구글링하여 많은 예제를 보면서 경우 제대로 동작하는 걸 알게 되었다.

Dictionary 는 Hashtable 의 제네릭 버전이다.


콤보박스와 Binding 하는 소스는 쉽게 찾을 수 있다. 하지만 선택된 값이나 Key 값을 알아내는 걸 찾기가 쉽지 않았다.

comboBox1.SelectedItem 이 어떤 결과를 보여주는지는 코드를 직접 실행해보면서 확인하면 된다.


Dictionary <TKey, TValue> dic = new Dictionary <TKey, TValue>();

첫번째 아이템은 Key 이고, 두번째 아이템은 Value 이다.




using System;
using System.Collections.Generic;
using System.Windows.Forms;
 
namespace comboBox_Dictionary
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            selectedcomboBox();
        }
 
        private void selectedcomboBox()
        {
            var cBox = new Dictionary<stringint>();
            cBox.Add("일요일",1);
            cBox.Add("월요일",2);
            cBox.Add("화요일",3);
            cBox.Add("수요일",4);
            cBox.Add("목요일",5);
            cBox.Add("금요일",6);
            cBox.Add("토요일",7);
 
            comboBox1.DataSource = new BindingSource(cBox, null);
            comboBox1.DisplayMember = "Key";
            comboBox1.ValueMember = "Value";
            comboBox1.SelectedValue = 5;
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            KeyValuePair<stringint> selectedPair = (KeyValuePair<stringint>)comboBox1.SelectedItem;
            textBox1.Text = string.Format("Selected Text : {0} and Value : {1}", selectedPair.Key, selectedPair.Value);
 
            //textBox1.Text = string.Format("Selected Text:{0} and Value:{1}",comboBox1.SelectedItem,comboBox1.SelectedValue);
 
        }
    }
}

첨부파일에는 코드가 약간 더 있다.


comboBox_Dictionary.zip



개발자가 아닌지라 자주 사용하지 않아 오래되면 기억이 나질 않는다.

그래서 추가로 알게된 사항을 기록해둔다.

동일한 함수를 여러번 호출해서 사용해야 할 경우가 있다.
이때는
selectedcomboBox(comboBox1) 으로 처리한다.
private void selectedcomboBox(ComboBox CB)
{
    var cBox = new Dictionary<string, int>();
    cBox.Add("일요일", 1);
    cBox.Add("월요일", 2);
    cBox.Add("화요일", 3);
    cBox.Add("수요일", 4);
    cBox.Add("목요일", 5);
    cBox.Add("금요일", 6);
    cBox.Add("토요일", 7);

    CB.DataSource = new BindingSource(cBox, null);
    CB.DisplayMember = "Key";
    CB.ValueMember = "Value";
    CB.SelectedValue = 5; // 몇번째 항목을 default 로 선택할 것인가?
}

자동으로 변경되는 값을 DB에서 가져와서 뿌려줘야 한다면
void cat1comboBox(ComboBox CB)
{
    CB.Items.Clear();
    CB.Items.Add("전체");
    try
    {
        myConn = new MySqlConnection(GetConnectionString());
        myConn.Open();

        string strqry = "select uid, classname from category where relateduid=0";
        strqry += " order by uid";
        adapter = new MySqlDataAdapter(strqry, myConn);
        DataSet cat1 = new DataSet();
        adapter.Fill(cat1);

        foreach (DataRow dr in cat1.Tables[0].Rows)
        {
            CB.Items.Add(dr["classname"]);
        }
        CB.SelectedIndex = 0; // 첫번째 아이템 선택
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        this.myConn.Close();
    }
}

private void cat1comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    cat2 = cat2comboBox(cat1comboBox1.SelectedItem.ToString(), cat2comboBox1); // 수정할 곳
    cat1name1 = cat1comboBox1.SelectedItem.ToString(); // TabPage1 의 cat1comboBox1

    myConn = new MySqlConnection(GetConnectionString());
    myConn.Open();

    string strqry = "select uid from category";
    strqry += " where relateduid=0 and classname='" + cat1name1 + "' "; // 수정할 곳

    MySqlCommand cmd = new MySqlCommand(strqry, myConn);
    cmd.CommandType = CommandType.Text;
    MySqlDataReader dr = cmd.ExecuteReader();
    while (dr.Read())
    {
        cat1uid1 = dr.GetString(0); // 수정할 곳
    }
    dr.Close();
    myConn.Close();
}


'C# > 문법 및 기능' 카테고리의 다른 글

자바와 C#의 차이점  (0) 2016.12.27
C# NameValueCollection  (0) 2016.03.20
C# Directory (폴더) 생성 및 삭제  (0) 2016.01.16
C# 시간 메소드  (0) 2016.01.15
C# 파일 입출력 개념 정리  (0) 2016.01.05
블로그 이미지

Link2Me

,
728x90

C# Context Menu 를 만들 때 서브 메뉴가 보이거나 보이지 않게 처리하는 방법이다.

마우스 우클릭을 해서 보이는 Context Menu 를 칼럼에 따라 메뉴가 보이게, 안보이게 처리하는 걸 시도해봤다.

Context Menu 는 메뉴 생성하는 곳에서 생성을 했다. 순서를 변경하는 걸 해보려고 했더니 안된다.

메뉴를 보이게 보이지 않게 처리하는 것은 Visible = true, false 로 선택 옵션을 준다.

dataGridView1 에서 필요해서 CellMouseClick 이벤트를 등록한 다음에

아래와 같이 메뉴를 선택적으로 if 조건을 주면 칼럼에서 메뉴가 다르게 보인다.

보여줘야 할 메뉴가 너무 많다면 이런 방법을 시도해보는 것도 좋을 것이다.


private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == 1)
    {
        NaverToolStripMenuItem1.Visible = true;
        DaumToolStripMenuItem.Visible = true;
        GoogleToolStripMenuItem.Visible = true;
        toolStripMenuItem11.Visible = true;
    }
    else if (e.ColumnIndex == 2)
    {
        NaverToolStripMenuItem1.Visible = false;
        DaumToolStripMenuItem.Visible = true;
        GoogleToolStripMenuItem.Visible = true;
        toolStripMenuItem11.Visible = false;
    }
    else
    {
        NaverToolStripMenuItem1.Visible = false;
        DaumToolStripMenuItem.Visible = false;
        GoogleToolStripMenuItem.Visible = false;
        toolStripMenuItem11.Visible = false;
    }
}


칼럼에 따라 Context Menu 를 동적으로 생성하는 것도 나중에 한번 해봐야겠다.


블로그 이미지

Link2Me

,
728x90

텍스트 파일을 읽어서 ListView 에 뿌리는 예제 코드다.

텍스트 파일의 인코딩 방식은 default 방식인 ANSI 이고, listView 를 직접 선택할 수 있게 코드를 작성했다.

파일을 Line 단위로 읽어서

Split 구분자로 칼럼 구분을 하고, 칼럼 구분된 배열 요소를 ListView 에 저장한다.


private void getTextFile_Click(object sender, EventArgs e)
{
    using (OpenFileDialog dlg = new OpenFileDialog())
    {
        dlg.Filter = "TextFile (*.txt) | *.txt";
        if (dlg.ShowDialog() == DialogResult.OK)
        {
            TextFileRead(dlg.FileName, listView1);
        }
    }
}

public void TextFileRead(string fileName, ListView LV)
{
    string delimiter = "/";  // 구분자
    using (var sr = new StreamReader(fileName, System.Text.Encoding.Default, true))
    {
        string line = null;
        LV.Items.Clear();  // 데이터 초기화
        while ((line = sr.ReadLine()) != null)
        {
            string[] columns = line.Split(new string[] { delimiter }, StringSplitOptions.None);

            ListViewItem lvt = new ListViewItem(columns[0]);
            lvt.SubItems.Add(columns[1]);
            lvt.SubItems.Add(columns[2]);
            LV.Items.Add(lvt);
        }
        sr.Close();
    }
}


칼럼의 갯수를 동적으로 하고자 한다면

ListViewItem lvt = new ListViewItem(columns[0]);
for (int col = 1; col < columns.Length; col++)
{
    lvt.SubItems.Add(columns[col]);
}
LV.Items.Add(lvt);
로 코드를 변경해주면 된다.


블로그 이미지

Link2Me

,
728x90

foreach 문

- 순차접근을 기반으로 한다.

- 임의 접근이 불가능한 컬렉션을 사용할 때 적합하다.


for 문

- 특정 조건이 성립할 때까지 반복한다.

- 인덱스를 하나씩 증가시킨다. → 인덱스가 성능을 저하시킨다.



이중 for 문을 사용하면 속도가 상당히 느리다.

빠른 속도를 기대하는 경우에 while 문을 사용하면 빠르다.

블로그 이미지

Link2Me

,
728x90

dataGridView cell 에 툴팁이 보이게 하는 걸 알고 싶어 테스트를 해봤다.

두가지 모두 정상적으로 잘 동작되었다.


방법 1

private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
    dataGridView1.CellToolTipTextNeeded += new DataGridViewCellToolTipTextNeededEventHandler(dataGridView1_CellToolTipTextNeeded);
}

void dataGridView1_CellToolTipTextNeeded(object sender, DataGridViewCellToolTipTextNeededEventArgs e)
{
    if (e.ColumnIndex == this.dataGridView1.Columns["Price"].Index)
    {
        e.ToolTipText = this.dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();
    }
}


방법2
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if ((e.ColumnIndex == this.dataGridView1.Columns["Price"].Index) && e.Value != null)
    {
        DataGridViewCell cell = this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
        cell.ToolTipText = this.dataGridView1.Rows[e.RowIndex].Cells[3].Value.ToString();
    }
}


일반적인 툴팁 사용은

MouseHover 이벤트를 발생시켜 보여주고 싶은 메시지를 보여주면 된다.

private void expandSearch_MouseHover(object sender, EventArgs e)
{

    toolTip1.IsBalloon = true;  // 풍선도움말 모양으로

    toolTip1.SetToolTip(expandSearch, "전체 DB 대상 검색");
}


툴팁은 0.5초 후에 나타나고 5초뒤에 사라지는 것이 기본이다.

프로그램이 Load 될 때에 보여주고 싶은 툴팁을 지정해줘도 된다.


블로그 이미지

Link2Me

,
728x90

엑셀 내보내기가 속도가 너무 느리다는 답변을 보고 다시 테스트를 해봤다.

4만개의 데이터를 CSV 로 내보내기하는데 2초가 걸리지 않았다.

엑셀 내보내기를 했더니 무려 11분 12초가 걸렸다.

엑셀 내보내기 로직은 더 좋은 로직을 찾아보고 구현해야 할 거 같다.

PHP 에서 내보내기 테스트를 해봤을 때도 for 문 특히 2중 for 문을 사용하면 속도가 매우 느렸다.

하지만 while 문을 사용하면 속도가 엄청 빨랐다.


private void Save_ExportToCSVFile(string fileName, DataGridView dgv, bool elapsedtime)
{
    string delimiter = ";";  // 구분자
    FileStream fs = new FileStream(fileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
    StreamWriter csvExport = new StreamWriter(fs, System.Text.Encoding.UTF8);

    try
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); // 동작시간 체크
        if (elapsedtime == true)
        {
            sw.Start();
        }

        using (var myConn = new MySqlConnection(ConnectionString))
        {
            myConn.Open();
            string strqry = "select 칼럼명 from 테이블명 Where 조건문 ";
            using (var cmd = new MySqlCommand(strqry, myConn))
            {
                using (MySqlDataReader reader = cmd.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            // 파일로 저장할 정보 기록
                            csvExport.Write(reader.GetString(0)); csvExport.Write(delimiter);
                            csvExport.Write(reader.GetString(1)); csvExport.Write(delimiter);
                            csvExport.Write(reader.GetString(2)); csvExport.Write(delimiter);
                            csvExport.Write(reader.GetString(3));
                            csvExport.WriteLine();
                        }
                    }
                    else
                    {
                        MessageBox.Show("데이터가 없습니다");
                    }
                }
            }
            myConn.Close();
        }
        csvExport.Flush(); // flush from the buffers.
        csvExport.Close();
        fs.Close();

        if (elapsedtime == true)
        {
            sw.Stop();
            MessageBox.Show("소요시간 : " + sw.Elapsed.ToString() + " 이고 CSV 파일 저장완료");
        }
        else
        {
            MessageBox.Show("CSV 파일이 저장되었습니다");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        throw;  // 비정상적인 상황(예외)이 발생한 경우 이를 알리는 데 사용
    }
}


'C# > C# SQL' 카테고리의 다른 글

C# MySQL 엑셀로 내보내기  (0) 2016.08.28
C# MySQL Update  (0) 2016.08.22
C# MySqlDataReader Format  (0) 2016.01.28
C# SQLite 데이터 삭제 (transaction 반영)  (0) 2016.01.14
C# SQLite dataGridView1 에 Select  (0) 2016.01.14
블로그 이미지

Link2Me

,
728x90

MySQL DB 데이터를 읽은 일반적인 포멧을 만들어 주고 사용하면 좋을거 같아서 포멧을 작성했다.

이 포멧은 SQLite, SQL, OleDB 등에서도 동일하게 사용 가능하다.

데이터를 읽어서 dataGridView, DataTable, listView 에 출력되도록 할 수도 있고

파일에 출력(저장)하게 할 수도 있다.


try
{
    using (var myConn = new MySqlConnection(ConnectionString))
    {
        myConn.Open();
        string strqry = "select 칼럼명 from 테이블명 Where 조건문 ";
        using (var cmd = new MySqlCommand(strqry, myConn))
        {
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {                            

                       reader.GetString(0);
                }

            }
        }
        myConn.Close();
    }
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
    throw;  // 비정상적인 상황(예외)이 발생한 경우 이를 알리는 데 사용
}

블로그 이미지

Link2Me

,
728x90

C#에서 폼의 크기를 고정하고 싶을 경우에




블로그 이미지

Link2Me

,
728x90

MySQL 데이터 Update 를 하면서 화면 갱신 문제처리에 부딪쳤다. 현재 작업하는 화면을 거의 유지하면서 MySQL 데이터 Update 를 해야 한다.


데이터 업데이트후 MySQL 다시 조회(Select) 루틴으로 하면 매번 화면의 current cell 상태를 잃어버린다. 이러다보니 너무 번거롭고 귀찮다.


foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
    string uid = row.Cells[2].Value.ToString();
    MessageBox.Show("index :" + row.Index.ToString() + " uid : " + uid);
    dataGridView1.Rows.RemoveAt(row.Index);  // 셀 삭제
}


선택된 행만 셀삭제 처리를 해보니까 선택된 행은 모두 삭제되고 마지막 셀 바로 이전셀이 자동으로 현재의 셀로 선택된다.


int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
int rowIndex = dataGridView1.CurrentCell.RowIndex;


CurrentCell 의 값을 가지고 작업해보면 항상 마지막에 선택된 셀의 값만 반환한다.

따라서 이건 원하는 결과를 만들어주지 못해서 패스.


FullRowSelect 로 하다보니 화면에서 보기가 별로 안좋다.

그래서 CellSelect 방식으로 테스트를 해봤다.


foreach (DataGridViewCell row in dataGridView1.SelectedCells)
{
    string uid = dataGridView1.Rows[row.RowIndex].Cells[2].Value.ToString();
    MessageBox.Show("index :" +
row.RowIndex.ToString()+ " uid : " + uid);
    dataGridView1.Rows.RemoveAt(
row.RowIndex);  // 셀 삭제
}


셀 단위이지만 선택된 셀의 RowIndex 를 구하면 원하는 행의 값을 얻어낼 수가 있다.


셀 단위로 선택하면 오류를 범하기 쉬운 문제를 방지하기 위해서 특정한 칼럼만 선택될 때 동작하도록 if 문을 추가했다.

foreach (DataGridViewCell row in dataGridView1.SelectedCells)
{
    if (row.ColumnIndex == 3)
    {
        string uid = dataGridView1.Rows[row.RowIndex].Cells[2].Value.ToString();
        dataGridView1.Rows.RemoveAt(row.RowIndex);  // 셀 삭제
    }
}


테스트를 해보고 나서 MySQL DB와 연결해서 작업을 했더니 완벽하게 원하는 결과가 나온다.

private void CheckedData(DataGridView dgv, int checkingcode)
{
    myConn = new MySqlConnection(GetConnectionString());
    if (myConn.State == ConnectionState.Closed)
    {
        myConn.Open();
    }

    try
    {
        foreach (DataGridViewCell row in dgv.SelectedCells)
        {
            if (row.ColumnIndex == 3)
            {
                string uid = dgv.Rows[row.RowIndex].Cells["uid"].Value.ToString();
                string content = dgv.Rows[row.RowIndex].Cells["content"].Value.ToString();

                if (content == null || content.Equals("")) { continue; }
                string strqry = string.Format("UPDATE data SET checkingcode={0}, content='{1}' Where uid ={2}", checkingcode, content.Trim(), uid);
                MySqlCommand cmd = new MySqlCommand(strqry, myConn);
                cmd.ExecuteNonQuery();
                cmd.Dispose();
                dgv.Rows.RemoveAt(row.RowIndex);  // 셀 삭제
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        if (myConn.State == ConnectionState.Open)
        {
            myConn.Close();
        }
    }
}


블로그 이미지

Link2Me

,
728x90

인터넷에 있는 파일을 읽어서 원하는 내용을 추출할 때 사용하는 코드이다.

이벤트 처리에 대한 개념이 잡히면서 MSDN 찾아보고 구글링 예제를 보면 점점 더 알게된다.


WebClient 클래스 : https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=KO-KR&k=k%28System.Net.WebClient%29;k%28TargetFrameworkMoniker-.NETFramework

using System.Net;

private void webFileRead()
{
    string serverfileName = "setup.txt";
    string URLPath = "http://www.abc.com/app/";

    WebClient client = new WebClient();
    Stream stream = client.OpenRead(URLPath + serverfileName);
    StreamReader reader = new StreamReader(stream);
    string readText = reader.ReadToEnd();
    //MessageBox.Show(readText);
    string serverVersion = SSplit(SSplit(readText, "[Version]", 1), "[", 0).Replace("\r\n", "").Trim();
    MessageBox.Show(serverVersion);
}

public static string SSplit(string _body, string _parseString, int index)
{
    string varTemp = _body.Split(new string[] { _parseString }, StringSplitOptions.None)[index];
    return varTemp;
}



WebRequest 클래스를 이용하여 웹 파일 내용을 확인하는 코드이다.

private string getSVersion()
{
    string serverfileName = "setup.txt";
    string URLPath = "http://www.abc.com/app/";

    WebRequest request = WebRequest.Create(URLPath + serverfileName);
    WebResponse response = request.GetResponse();
    string readText = new StreamReader(response.GetResponseStream()).ReadToEnd();
    string serverVersion = SSplit(SSplit(readText, "[Version]", 1), "[", 0).Replace("\r\n", "").Trim();

    return serverVersion;
}


웹 파일 다운로드 진행률 표시 처리 구현을 위한 준비 작업

WebClient 클래스의 이벤트를 찾아보면 파일 다운로드를 구현할 때 파일의 다운로드 진행상태 등을 알 수 있는 예제를 제공하고 있다.

https://msdn.microsoft.com/ko-kr/library/system.net.webclient.downloadprogresschanged%28v=vs.110%29.aspx


WebClient.DownloadProgressChanged 이벤트
// 비동기 다운로드 작업을 통해 데이터 전체 또는 일부를 성공적으로 전송하면 발생
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgress);
private void DownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
   progressBar1 = e.ProgressPercentage;
   label1.Text = progressBar1.Value.ToString() + "%";
}

WebClient.DownloadFileCompleted 이벤트
// 비동기 파일 다운로드 작업이 완료되면 발생
client.DownloadFileCompleted += new AsyncCompletedEventHandler (DownloadFileComplete);
private void DownloadFileComplete(object sender, AsyncCompletedEventArgs e)
{
   MessageBox.Show("다운로드가 완료되었습니다");
}


블로그 이미지

Link2Me

,