string strUri_get_stripinfos = strUri + DMCMD_get_stripinfos;


            try

            {

                WebRequest wrGETURL;

                wrGETURL = WebRequest.Create(strUri_get_stripinfos);


                Stream objStream;

                objStream = wrGETURL.GetResponse().GetResponseStream();


                StreamReader objReader = new StreamReader(objStream);


                string sLine = "";

                int i = 0;


                while (sLine != null)

                {

                    i++;

                    sLine = objReader.ReadLine();

                    if (sLine != null)

                    {

                        Console.WriteLine("{0}:{1}", i, sLine);

                        if (sLine.Contains("stripinfos") == true)

                        {

                            string response = sLine.Replace("\\", "");

                            response = sLine.Replace("\"", "");

                            response = response.Replace("{", "");

                            response = response.Replace("}", "");

                            response = response.Replace("stripinfos:", "");

                            response = response.Replace("[", "");

                            response = response.Replace("]", "");

                            string[] valuelist = response.Split(',');

                            if (valuelist.Count() > 0)

                            {

                                int selectedindex = -1;

                                List<string> striplist = new List<string>();

                                stripinfolist.Clear();

                                for (int k = 0; k < valuelist.Count(); k++)

                                {

                                    string[] temp = valuelist[k].Split('/');

                                    int tempvalue = 0;

                                    StripInfo info = new StripInfo();

                                    info.lot_number = temp[0];

                                    striplist.Add(temp[0]);

                                    if (temp.Length > 1 && temp[1] == "true")

                                    {

                                        selectedindex = k;

                                        info.aisdefaultatportable = true;

                                    }


                                    if (temp.Length > 2 && int.TryParse(temp[2], out tempvalue) == true)

                                    {

                                        info.min_cs_A_value = tempvalue;

                                    }


                                    if (temp.Length > 3 && int.TryParse(temp[3], out tempvalue) == true)

                                    {

                                        info.max_cs_A_value = tempvalue;

                                    }


                                    if (temp.Length > 4 && int.TryParse(temp[4], out tempvalue) == true)

                                    {

                                        info.min_cs_B_value = tempvalue;

                                    }


                                    if (temp.Length > 5 && int.TryParse(temp[5], out tempvalue) == true)

                                    {

                                        info.max_cs_B_value = tempvalue;

                                    }


                                    stripinfolist.Add(info);                                    

                                }                               


                                stripinfocombobox.IsEnabled = true;

                                stripinfocombobox.ItemsSource = striplist;

                                stripinfocombobox.SelectedIndex = selectedindex;

                                break;

                            }

                            else

                            {

                                

                            }

                        }

                    }

                }


            }

            catch (Exception err)

            {

                string error_msg = "서버에 접속하지 못했거나 해당 기능이 서버에 반영되지 않았습니다. \r\n접속 주소는 " + strUri_get_stripinfos + " 입니다\r\n메세지 :: " + err.Message;

                LogManager.Log(3, error_msg);

                stripinfocombobox.ItemsSource = null;

                stripinfocombobox.IsEnabled = false;

            }

by 무위자연 2018. 1. 10. 17:12


string '1234' 를 8자로 만들 때 '00001234'로 0으로 채워넣고 싶을 때

(padding 한다고 할 수 있다)

value = value.PadLeft(8, '0'); //참 쉽죠

by 무위자연 2017. 8. 19. 22:06

간단하게 아이템을 변경하고 다시 넣어주는 방식으로 처리해본다.


<ListView...


 lvObservationData.ItemsSource = null;

 lvObservationData.ItemsSource = loadeddatalist;

by 무위자연 2017. 3. 8. 10:40

프로젝트 속성 > 빌드 > 하단의 "고급"을 선택한 다음에


나오는 팝업에서 디버그 정보의 옵션을 "none"으로 설정하면 된다.


보통 debug모드에서 full / release 모드에서는 pdb-only로 설정되어 있다.



by 무위자연 2017. 3. 7. 09:16



파일에 쓸 때


HistoryData data = new HistoryData();

            data.SerialNumber = loadedserial_number;

            data.OperatorID = tbOperatorID.Text;

            data.test_dttm = loadeddatalist[loadeddatalist.Count - 1].test_dttm;

            data.value = loadeddatalist[loadeddatalist.Count - 1].value;


            

            datalist.Historydata.Add(data);


            FileStream fs3 = new FileStream(history_filename, FileMode.Create, FileAccess.Write);

            XmlSerializer xs = new XmlSerializer(datalist.GetType());

            xs.Serialize(fs3, datalist);

            fs3.Close();            


파일에서 읽을 때


  FileStream fs4 = new FileStream(history_filename, FileMode.Open, FileAccess.Read);

            XmlSerializer xs2 = new XmlSerializer(datalist.GetType());

            datalist = (HistoryDataList)xs2.Deserialize(fs4);

            fs4.Close();


이 때 데이터 클래스는 public class 이면서 [serializable]을 붙여줘야 한다.

like this


    [Serializable]

    public class HistoryDataList

    {


by 무위자연 2017. 1. 13. 15:30


 string targfolder = Properties.Settings.Default.Target_Log;

 if(Directory.Exists(targfolder) != true)

 {

     Directory.CreateDirectory(targfolder);

  }

  targfolder += "\\datamanager_log_" + DateTime.Now.ToString("yyyyMMdd_hhmmss") + ".log";

  

ZipFile.CreateFromDirectory(Properties.Settings.Default.DM_Log, targfolder);                    


지정된 폴더 하위에 있는 파일을 지정된 파일명으로 압축한다.


압축율은 zip 상용 프로그램과 비슷하며 


해당 파일은 일반 zip 압축 해제로 열람이 가능하다.



by 무위자연 2016. 6. 30. 11:58

byte[] data = { 1, 2, 4, 8, 16, 32 };


string hex = BitConverter.ToString(data);


해당 string을 출력하면


01-02-04-08-10-20


"-"이 거슬린다면 replace를 쓰자.


string hex = BitConverter.ToString(data).Replace("-", string.Empty);

by 무위자연 2016. 3. 3. 10:17

원본

데이터 바인딩의 정의

데이터 바인딩은 응용프로그램 UI와 비지니스 논리를 서로 연결하는 프로세스이다. 바인딩 설정이 올바르고 데이터가 적절한 알림을 제공하는 경우에는 데이터의 값이 변경될때

데이터에 바인딩된 요소에 변경 내용이 자동으로 반영된다.

 

일반적인 용도는 서버 또는 로컬 구성 데이터를 폼이나 기타 UI 콘트롤에 배치하는 것.

 

기본 바인딩 개념

바인딩하려는 요소 및 데이터 소스의 특성에 관계 없이 각  바인딩은 항상 다름 그림에 나타나는 모델을 따릅니다.

<이미지 출처 : msdn https://msdn.microsoft.com/en-us/library/hh848246.aspx



  • 데이터 바인딩은 기본적으로 바인딩 대상과 바인딩 소스 사이의 다리 역할을 한다.
  • 대상 속성은 종속성 속성이어야 한다. UIElement 속성 대부분은 종속성 속성이며 읽기 전용 속성을 제외한 대부분의 종속성 속성은 기본적으로 데이터 바인딩을 지원한다.
  • DependencyObject 형식만 종속성 속성을 정의할수 있다.

 

소스 업데이트를 트리거하는 항목

TwoWay, OneWayToSource인 바인딩은 대상 속성의 변경 내용을 수신하고 해당 변경 내용을 다시 소스로 전파합니다. 이것을 소스 업데이트라고 한다.

텍스트를 편집하고 있을때나 텍스트 편집을 마치고 마우스를 TextBox 외부로 움직였을때 소스 값이 업데이트 될까요?  소스 업데이트는 바인딩의 UpdateSourceTrigger속성에 따라 결정된다.

UpdateSourceTrugger 값이 PropertyChanged이면 대상 속성이 변경되는 즉시 업데이트가 일어나고 LostFocus 이면 대상 속성이 포커스를 잃었을때에만 해당 값이 업데이트 된다.

 

바인딩 만들기

바인딩 소스 지정 - 여러 속성을 같은 소스에 바인딩할때 부모요소에 DataContext속성을 사용하는 방법이 유용하다. 개별적인 경우 DataContext 대신 Source속성을 이용할수도 있다.

값에 대한 경로 지정 - 바인딩 소스가 개체일때는 Path속성을 사용하여 바인딩에 사용할 값을 지정합니다.

 

데이터 변환

[ValueConversion(typeof(Color), typeof(SolidColorBrush))]
public class ColorBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Color color = (Color)value;
        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

ms752347.DataBindingConverterColorExample(ko-kr,VS.90).png

 

바인딩하는 형식에 있는 형식  변환기때문에 기본변환을 사용할수 있다.  형식변환기를 직접 구현하는 경우는

  • 데이터를 문화권에 따라 드라게 표시해야 하는 경우
  • 사용되는 데이터를 반드시 속성의 텍스트 값으로 변경할 필요는 없지만 이미지의 소스 또는 표시 텍스트의 색이나 스타일과 같은 다른 값으로 변경해야 하는 경우
  • 둘 이상의 콘트롤 또는 콘트롤의 여러 속성을 같은 데이터에 바인딩하는 경우
  • MultiBinding 의 경우 사용자 지정 IMultiValueConverter를 사용하여 바인딩의 값에서 최종 값을 생성한다.

 

 

컬렉션에 바인딩.

바인딩 소스 개체는 속성에서 데이터를 포함하는 단일 개체 또는 함께 그룹화되는 경우가 많은 다형성 개체의 데이터 컬렉션으로 취급될수 있다.

컬렉션 구현방법

IEnumberable 인터페이스를 구현하는 모든 컬렉션을 열거할수 있다. 그러나 컬렉션에 삽입이나 삭제를 수행할때 UI가 자동으로 업데이트되도록 동적 바인딩을 설정하려면

컬렉션에서 INotifyCollectionChanged 인터페이스를 구현해야 한다. 이 인터페이스는 내부컬렉션이 변경될때마다 발생해야 하는 이벤트를 노출한다.

WPF에서는 INotifyCollectionChanged 인터페이스를 노출하는 데이터 컬렉션에 대한 기본 제공 구현인 ObservableCollection(T) 클래스를 제공한다.

컬렉션뷰의 정의

컬렉셔뷰는 기본 소스 컬렉션  자체를 조작할 필요없이 필터, 정렬, 그룹화 쿼리를 기반으로 소스 콜력션을 탐색하고 표시하는 사용할수 있는 바인딩 소스 콜렉션의 최상위 계층으로 간주할수 있다.INOtifyCOllectionChanged 페이스가 소스 콜렉션에서 구현될 경우 CollectionChanged이벤트에서 발생되는 변경내용은 뷰로 전파됩니다.

뷰는 기본 소스 컬렉션을 변경하지 않으므로 각 소스 컬렉션에 여러개의 뷰를 연결하여 사용할수 있다.

뷰 사용법 중에 하나는 뷰 개체를 직접 인스턴스화한 다음 이를 바인딩 소 스로 사용하는 방법이다.

 

정렬

ex.

private void AddSorting(object sender, RoutedEventArgs args)
{  
    listingDataView.SortDescriptions.Add(
        new SortDescription("Category", ListSortDirection.Ascending));
    listingDataView.SortDescriptions.Add(
        new SortDescription("StartDate", ListSortDirection.Ascending));
}

 

필터

ex.

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

 

private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
    AuctionItem product = e.Item as AuctionItem;
    if (product != null)
    {
        // Filter out products with price 25 or above
        if (product.CurrentPrice < 25)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = false;
        }
    }
}

 

그룹화 - 뷰에서 그룹화 기능을 지원하므로 사용자는 컬렉션 뷰의 컬렉션을 놀리 그룹으로 분할할수 있다. 사용자가 그룹 목록을 제공할 경우 그룹은 명시적이며 그룹이 데이터에 따라 동적으로 생성될 경우 그룹은 암시적이다.

ex.// This groups the items in the view by the property "Category"
PropertyGroupDescription groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);

 

현재 레코드 포인터

컬렉션 뷰에서 개체를 탐색할수 있다. 탐색할때 레코드 포인터를 이동하여 컬렉션의 특정 위치에 있는 개체를 검색할수 있다.

현재 레코드 포인터 이동은 컬렉션에 적용되는 정렬 똔느 필터링과  몇 가지 상호 작용을 한다. 정렬이 적용되는 경우에는 선택한 마지막 레코드에 현재 레코드 포인터가 유지되지만

해당 레코드 주위에서 컬력센 뷰가 재구성됩니다. 

 

마스터-세부 바인딩 시나리오

 

데이터 템플릿

ex.

<DataTemplate DataType="{x:Type src:AuctionItem}">
    <Border BorderThickness="1" BorderBrush="Gray"
            Padding="7" Name="border" Margin="3" Width="500">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="86"/>
            <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>

            <Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
                     Fill="Yellow" Stroke="Black" StrokeThickness="1"
                     StrokeLineJoin="Round" Width="20" Height="20"
                     Stretch="Fill"
                     Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"
                     Visibility="Hidden" Name="star"/>

            <TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"
                       Name="descriptionTitle"
                       Style="{StaticResource smallTitleStyle}">Description:</TextBlock>
            <TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column="2"
                Text="{Binding Path=Description}"
                Style="{StaticResource textStyleTextBlock}"/>

            <TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"
                       Name="currentPriceTitle"
                       Style="{StaticResource smallTitleStyle}">Current Price:</TextBlock>
            <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>
                <TextBlock Name="CurrentPriceDTDataType"
                    Text="{Binding Path=CurrentPrice}"
                    Style="{StaticResource textStyleTextBlock}"/>
            </StackPanel>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Color</src:SpecialFeatures>
            </DataTrigger.Value>
          <DataTrigger.Setters>
            <Setter Property="BorderBrush" Value="DodgerBlue" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
          </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Highlight</src:SpecialFeatures>
            </DataTrigger.Value>
            <Setter Property="BorderBrush" Value="Orange" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="Visibility" Value="Visible" TargetName="star" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

데이터 템플릿을 사용하면 데이터를 컨트롤에 넣을수 있을뿐 아니라 데이터를 시각적으로 뛰어나게 표현할수 있다.

 

데이터 유효성 검사

사용자 입력을 받는 대부분의 응용프로그램은 사용자가 올바른 정보를 입력했는지 확인하기 위한 유효성 검사 논리가 필요하다 유효성 검사는 형식, 범위, 서식 또는 기타 응용프로그램별

요규사항을 기반으로 할수 있다.

ex 유효성 검사 규칙을 바인딩과 연결

<TextBox Name="StartPriceEntryForm" Grid.Row="2" Grid.Column="1"
    Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">
  <TextBox.Text>
    <Binding Path="StartPrice" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ExceptionValidationRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

WPF 데이터 바인딩 모델을 사용하면 ValidationRules를 Binding 객체와 연결할수 있다.

 

시각적 피드백 제공

ex.

<ControlTemplate x:Key="validationTemplate">
  <DockPanel>
    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
    <AdornedElementPlaceholder/>
  </DockPanel>
</ControlTemplate>

 

유효성 검사 프로세스

ms752347.DataBindingValidation(ko-kr,VS.90).png

  1.  대상 속성에서 소스 속성으로 값이 전송중인 경우 데이터 바인딩 엔진은 먼저 바인딩된 요소의 Validation.Errors 연결된 속성에 추가되었을 수 있는 ValidationError 를 모두 제거.
  2. 그런 다음 해당 Binding 에 대해 정의된 사용자 지정 ValidationRule 이 있는지 확인한 다음 있으면 해당 규칙 중 하나가 오류를 만나거나 모두 통과할때까지 각 ValidationRule에 대해 Validation 메소드를 호출합니다
  3. 통과되지 않은 사용자 지정 규칙이 있으면 바인딩 엔진은 ValidationError 개체를 만들어 바인딩된 요소의 Validation.Error 컬렉션에 추가합니다. Validation.Errors가 비어 있지 않으면 요소의 Validation.HasError연결된 속성은 ture로 설정됩니다. 또 Binding의 NotifyOnCalidationError속성이 true로 설정되어 있는 경우 바인딩 엔진은 요소에 대해 Validation.Error 연결된 이벤트를 발생시킨다
  4. 모든 규칙이 통과되는 경우 바인딩 엔진은 변환기를 호출합니다
  5. 변환기가 통과되면 바인딩 엔진은 소스 속성의 setter를 호출한다
  6. 바인딩에 연결된 ExceptionValidationRule이 있고 5 단계에서 예외가 throw되는 경우 바인딩 엔진은 UpdateSourceExceptionFilter가 있는지 확인합니다.

    UpdateSourceExceptionFilter 콜백을 사용하여 예외 처리를 위한 사용자 지정 처리기를 제공할수 있다. Binding에서 UpdateSourceExceptionFilter가 지정되지 않은 경우 바인딩 엔진은 예외가 있는 ValidationError를 만들어 바인딩된 요소의 Validation.Errors컬렉션에 추가합니다.

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 9. 24. 14:05
| 1 |