2010-08-02 3 views
1

일부 부호없는 long 값을 디코딩하는 응용 프로그램을 작성하려고합니다. 각 값의 형식은 다음과 같이 XML로 표현됩니다.WPF에서 XML 데이터 바인딩

<Project Name="Project1"> 
<Message Name="a"> 
    <BitField high="31" low="28"> 
    <value>0001</value> 
    <value>1010</value> 
    </Bitfield> 
    <BitField high="27" low="17"> 
    <value>000111101</value> 
    </BitField> 
    <BitField high="16" low="0">100h</BitField> 
</Message> 
</Project> 

이제 프로젝트 값이 콤보 박스에 나타납니다. 사용자가 콤보 상자에서 값을 선택하면 목록 상자에 메시지 유형이 표시되어야합니다. 그런 다음 사용자가 목록 상자에서 메시지 유형을 선택하면 보유 할 수있는 비트 필드와 값을 표시해야합니다. 이제 사용자가 각 비트 필드에 대한 값을 선택하면 최종 dword 값을 텍스트 상자에 표시해야합니다.

전체 XML을 구문 분석하지만 선택과 관련이없는 예제를 발견했습니다. 여기 사람들 도움이 필요해.

한 가지 더 사용자가 텍스트 상자에 dword 값을 입력 할 수 있습니다. 이제 텍스트 상자에서 dword를 디코딩하는 역방향 바인딩을 수행하고 위에 설명 된 UI를 사용하여 해당 메시지 + 값을 표시 할 수 있습니까?

업데이트 : 이제 프로젝트 값을 표시하는 콤보 상자와 메시지를 표시하는 목록 상자간에 바인딩을 수행했습니다. 내가해야 할 다음 일은 사용자가 목록 상자에서 메시지를 선택할 때 비트 필드가 "높음", "낮음", "값/@ 이름"(여기서는 표시되지 않음) 행으로 표시되어야하고 다음에 값 (값/@ 이름에 바인드 됨)을 열로 사용합니다. 값/@ 이름은 콤보 상자로 표시되어야합니다. 확실히 내가 dataGrid에서 이것을 할 수 있지만 .net 3.5를 사용하여 여기에서 대안을 찾고 있습니다. 또한 값 텍스트 블록은 < 값> 노드가 xml에없는 경우 편집 할 수 있어야합니다. 마지막으로 "값"열을 가로 질러 항목을 DWORD에 압축해야합니다. DataGrid없이 XAML에서이 작업을 수행 할 수 있습니까? .NET 3.5에 대한 DataGrid의 대안은 무엇입니까?

+0

C# WPF 란 무엇입니까? VB.NET WPF와는 다른가요? –

+0

John에게 : WPF는 CLR (공용 언어 런타임) 코드와 통합됩니다. AFAIK 이것은 .NET 언어 중 하나에서 생성 될 수 있지만 C# .NET과 VB.NET에서 확실히 생성되므로 기본적으로 사용되는 언어와 상관없이 동일한 기능을 사용할 수 있습니다. –

답변

2

여기서 XML 파싱 문제와 변환 문제라는 두 가지 문제가 있습니다.

바인딩이 작동하려면 XML을 값을 나타내는 클래스로 구문 분석해야합니다. 전환 문제는 TypeConverters이라는 개념을 사용하는 것이 매우 간단합니다. XML 구문 분석 문제의 경우 LINQ-to-XML을 강조하고 싶습니다. 생각하는 것은 꿀벌 무릎입니다. 그것의 몇 줄은 XML 소스에서 가장 복잡한 객체 그래프까지도 재구성 할 수 있습니다. 예를 들어 Project/Message/BitField의 경우 패턴을 제공하는 솔루션을 부분적으로 구현했습니다.

"LoadFromXml"메서드에 유의하십시오. 이것은 객체 그래프를 채우는 linq-to-xml 표현식을 사용합니다. 당신의 XML 소스에서이 쿼리 변경은 컬렉션 노드 (즉, 나)를 기대하는 것을 한 가지가

public class Project 
    { 
     public string Name { get; set; } 
     public List<Message> MessageCollection = new List<Message>(); 

     public void LoadFromXml(string xmlString) 
     { 
      // From System.Xml.Linq 
      XDocument xDocument = XDocument.Parse(xmlString); 

      // The following assumes your XML is well formed, is not missing attributes and has no type conversion problems. In 
      // other words, there is (almost) zero error checking. 
      if (xDocument.Document != null) 
      { 
       XElement projectElement = xDocument.Element("Project"); 

       if (projectElement != null) 
       { 
        Name = projectElement.Attribute("Name") == null ? "Untitled Project" : projectElement.Attribute("Name").Value; 

        MessageCollection = new List<Message> 
         (from message in xDocument.Element("Project").Elements("Messages") 
         select new Message() 
           { 
            Name = message.Attribute("Name").Value, 
            BitfieldCollection = new List<BitField> 
             (from bitField in message.Elements("Bitfields") 
              select new BitField() {High = int.Parse(bitField.Attribute("High").Value), Low = int.Parse(bitField.Attribute("Low").Value)}) 
           } 
         ); 
       } 
      } 
     } 
    } 

    public class Message 
    { 
     public string Name { get; set; } 
     public List<BitField> BitfieldCollection = new List<BitField>(); 
    } 

    public class BitField 
    { 
     public int High { get; set; } 
     public int Low { get; set; } 
     public List<string> ValueCollection = new List<string>(); 
    } 
1

당신은 확실히 마음에 모델의 분리를 유지할 필요가 수집 노드 (예)로 묶어야합니다 모델의보기 및 외부 표현. 실제 XML의 크기와 API의 종류에 따라 TOU는 편하게 사용할 수 있습니다. XML을 읽고 실제 객체로 변환하여 UI의 모델로 사용할 수있는 몇 가지 다른 방법을 사용할 수 있습니다. 그 분리를 명심하는 것이 중요합니다.

XML이 다른 처리의 실제 데이터라고 가정합니다. 즉, 프로젝트 태그가 많고 Message 태그가 많으며 비트 필드 스팬이 메시지마다 다릅니다. 이 가정이 잘못되어 전체 응용 프로그램이나 하나의 큰 파일에있는 모든 메시지에 대해 비트 필드 스팬이 고정되면 시간과 공간을 절약 할 수 있습니다.

그래서 모든 것이 변경 가능하다고 가정하면 태그에서 값을 가져 오는 가장 중요한 방법은 XPathDocumen을 만들고 XPath로 문자열 컨텐 츠 또는 구성으로 유지할 수있는 것을 선택하는 것입니다.예를 들어이 당신에게

//Project/Message/BitField/Value 

모든 값 태그 (지금이라고 노드)를 줄 것이다 및 노드 객체가 부모 포인터를 가지고 있기 때문에 당신은 그 대상을 (목록 또는 배열) 부모를 공유하는 모든 값을 수집 갈 수있다 부모 (BitField), 유지하고 XmlNode (부모 포인터가 있는지 확인하십시오. 모든 BitField 객체를 갖게되면 비슷한 방식으로 그룹을 검사하여 부모 (Message)로 다시 스캔하고 Project-s를 다시 얻을 수 있습니다. 그것은 단지 하나의 방법 일뿐입니다. 짧은 XPath를 사용하여 BitField에서 수집을 시작하고 자녀를 직접 붙잡을 수 있습니다.

XML 태그를 그대로 나타내는 몇 가지 일반 클래스 (각 필드에 대해 하나의 데이터 멤버, 각 태그에 대해 하나의 클래스)를 만들고 XmlSerialization에 대한 특성을 그 위에 놓을 수도 있습니다. 이름을 얻으려면 약간의 시련이 필요 하겠지만, 함수 호출로 전체 파일을 "비 직렬화"하고 배열이나 배열의 배열을 .NET에서받을 수 있습니다.

파일이 너무 크면 XmlTextReader를 사용하고 파일을 위에서 아래로 스캔해야합니다. 즉, XPath 선택의 반대 방향입니다 (XmlTextReader는 구문 분석이 가장 가볍고 톤을 생성하지 않습니다). 여분의 객체가 있지만 몇 가지 모양으로 반복해야하고 일방적이므로 부모에서 자식으로 항상 "걸어 가야"합니다.

UI를 사용하면 조금만 실험 해 볼 시간이 있다면 콤보 박스 3 개와 텍스트 필드 1 개가있는 경계 상자를 만든 다음 그 목록을 만들어 볼 가치가 있습니다. 그리드의 메카니즘을 준수 할 필요가 없다.

아, 그리고 XML 형식에 영향을 주면 ppl이 값 하나만있는 경우에도 해당 값을 항상 값 태그에 넣으려고합니다. XML 파일은 조금 더 길어 지지만 처리가 간소화됩니다.

1

데이터 바인딩 및 XMLReaders를 사용하여 수행 할 수 있습니다. 먼저 부모 패널 내부에 UI를 작성하십시오 (이 방법으로 패널의 데이터 인터페이스를 설정할 수 있고 하위 컨트롤은 모두이 컨텍스트를 상속받습니다).

다음으로 맞춤 클래스를 만듭니다 (프로젝트라고 부름). 이 클래스의 각 필드가 PropertyDependencyInfo를 업데이트하는지 확인하십시오. 그렇지 않으면 데이터 바인딩이 작동하지 않습니다.

그런 다음 UI 컨트롤의 Content 또는 Itemssource 속성을 Project 클래스의 필드에 바인딩하십시오.

그런 다음 XMLReader 클래스 또는 XPathReader 클래스를 사용하여 XML을 읽는 코드를 만듭니다. 그런 다음 파일에서 데이터에 액세스 한 경우 읽을 데이터와 일치하도록 새 Project 개체의 필드를 설정합니다.

프로젝트 개체가 인스턴스화되고 XML의 값이 올바르게 할당되면 부모 Panel을 UI의 DataContext 속성에서 Project 개체로 설정합니다. 그러면 모든 UI 필드가 업데이트됩니다.

다른 파일을로드해야하는 경우 XML 읽기를 다른 파일 이름으로 반복하면됩니다. 당신의 업데이트로

: 누구의 RowDefinition과 ColumnDefinition 자녀 수를 증가 및 감소 관리하기 위해 만든 런타임에 수정

그리드/UniformGrid 제어 : 행과 열을 사용하여 관리 할 수있는 다음 중 하나 필드의

또는 : 각 열에 하나씩 StackPanels 집합 (열의 수가 변경되지 않음).Value/@ name 열의 StackPanel에 Comboboxes를 직접 추가하거나 StackPanel의 ItemsTemplate을 수정할 수 있습니다 (컨테이너가있는 경우 지금은 확인할 수 없습니다).

이 질문은 다양한 주제를 다루기 때문에 몇 가지 하위 질문으로 나누어 져야하며, 문제에 특별히 관련된 질문이 있으면 문제의 각 측면에 대한 자세한 대답을 얻을 가능성이 더 큽니다.

관련 문제