2014-12-23 1 views
2

XMLDataProvider를 통해 XML 데이터를 사용하는 wpf 창이 있습니다. 스크린이 ... 격자를 기반으로 모든 데이터는 다음과 같은 다음과 같은 XML 소스와 xmldataprovider 코드 뒤에 요소 값 사용

<Grid.DataContext> 
    <XmlDataProvider x:Name="Data" XPath="Book/Page" /> 
</Grid.DataContext> 

뒤에 코드에서 설정되고 ... XML을 정의한 후, 올바르게 표시되는

InitializeComponent(); 

string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); 
Data.Source = new Uri(appPath + @"\SNG.xml"); 

지금까지 모두 좋았습니다. 하지만 지금은 코드 뒤에있는 xml 파일에서 요소 중 하나를 읽을 필요가 있습니다. 내 모든 검색 및 내가 찾은 유일한 방법은 그것을 보이지 않는 컨트롤에 바인딩 한 다음 컨트롤에서 데이터를 읽는 것입니다. 예 : 나는이 (가) XAML에서 다음 한 XML에서 BookRef ...

뒤에 코드에서 다음
TextBlock Name="BookRefTextBox" Visibility="Hidden" Text="{Binding [email protected]}"/> 

...이 작동

string bookRef = BookRefTextBox.Text; 

를 읽고 난 후, 제공된 데이터를 사용할 수 있습니다 xml 파일에서 ...하지만 그것은 퍼지처럼 느껴집니다. 코드 숨김 섹션에서 xml 파일의 일부 값을 가져 오는 더 좋은 방법이 있습니까?

편집 :

내가 대신 할 내가 찾은 몇 가지 예로서 Grid.DataContext에서의 Windows.ResourcesXmlDataProvider을 넣어 시도했습니다 말을 잊으.

그러나 코드 뒤에 XML 파일의 경로를 설정하는 방법을 찾을 수 없습니다. Windows.Resource에 추가하면 Xml 파일에서 데이터에 액세스하는 방법을 쉽게 찾을 수 없습니다.

EDIT2 : 다음은 XML 파일의 예입니다. 여러 권의 책이 있습니다.

<Books> 
    <Book Id="1" BookRef="12345" Name="My Book Name" Author="Author" Pages="2" > 
    <Page PageId="1"/> 
    <Page PageId="2"/> 
    </Book> 
    <Book Id="1" BookRef="67890" Name="My Second Book Name" Author="Author 2" Pages="1" > 
    <Page PageId="1"/> 
    </Book> 
</Books> 

답변

0

나는 마침내 숨겨진 컨트롤의 사용을 피하는 답을 찾았다 고 생각합니다. 먼저 그의 대답에 대한 kennyzx 덕분에 많은 감사를 드렸습니다. 아직 숨겨진 컨트롤을 사용해 왔지만이 대답을 이끌어 내는데 매우 귀중했습니다.

Grid.Context에 XmlDataProvider를 두는 대신 Window.Resources로 이동하고 CollectionViewSource를 추가하여 동행했습니다.

<Window.Resources>   
    <XmlDataProvider x:Name="books" x:Key="bookData" XPath="Books/Book/Page"/> 
    <CollectionViewSource x:Key="collBookData" Source="{StaticResource bookData}"/> 
</Window.Resources> 

새로운 XmlDataProvider 뒤에 코드로 정의되고, 윈도우의 생성자에서 XAML Windows.Resources에 정의 된 기준에 설정된다.

XmlDataProvider bookData; 

    public BookPage() 
    { 
     InitializeComponent(); 

     string appPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); 
     bookData = (XmlDataProvider)this.Resources["bookData"]; 
     bookData.Source = new Uri(appPath + @"\SNG.xml"); 
    } 

Grid의 DataContext는 CollectionViewSource로 설정됩니다. 그 대신 각각의 제어에 지정 될 수 있기

<Grid.DataContext> 
     <Binding Source="{StaticResource collBookData}"/> 
    </Grid.DataContext> 

위에은 100 % 필요하지만,이 방법은 간단한 폼의 각 제어에 바인딩한다. (이 솔루션에는 숨겨진 컨트롤이 없으며 실제로 보여주고 싶은 컨트롤 만 표시). 예를 들어 ...

<TextBlock Name="myTextBlockName" Style="{StaticResource MyTextBlockStyle}" Text="{Binding XPath=../@BookRef}" /> 

마지막으로 코드의 XML에서 데이터를 읽을 비트. 그냥 여담으로

 XmlNode currentXmlNode = bookData.Document.SelectNodes("Books/Book/Page").Item(collBookData.View.CurrentPosition); 
     string currentBookRef = currentXmlNode.ParentNode.Attributes["BookRef"].Value; 

이,이 솔루션은 또한 나를 표시되는 현재 페이지를 변경 collBookData.View에 대해 MoveCurrentToPrevious 및 MoveCurrentToNext을 사용할 수 있습니다 (이전에 해당 할 수있는 숨겨진 목록 상자 컨트롤을했고 그와 행복하지 않았다 솔루션 중 하나).

2

확인을 클릭하면 더 복잡합니다.

현재 표시된 페이지를 BookRefTextBox의 텍스트와 동기화해야하는 것이 맞습니다. 따라서 XmlDataProvider 상단에 나는 CollectionViewSource을 정의합니다.이 페이지는 현재 표시된 페이지를 추적하는 데 사용할 수 있습니다. 아래의 XAML 코드에서

, 모두 BookRefTextBoxlistBox1 (I 페이지를 표시 할 목록 상자를 사용) 같은 CollectionViewSource에 결합하고, 이 IsSynchronizedWithCurrentItem이 = "진정한"는는, 현재 항목이 업데이트 선택한 페이지 인 경우 설정하면된다 변경되었습니다.

재미있는 점은 BookRefTextBox.Test의 XPath 표현식입니다. XPath=../@BookRef은 BookRefTextBox의 텍스트가 Find the parent element of the current page- which is Book, and display its BookRef attribute"임을 의미합니다.

창의 전체 XAML.

<Window x:Class="MyNamespace.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <XmlDataProvider x:Key="userDataXmlDataProvider1" Source="/Data/XMLFile1.xml" XPath="Books/Book/Page"/> 
     <CollectionViewSource x:Key="userDataCollectionViewSource1" Source="{StaticResource userDataXmlDataProvider1}"/> 
    </Window.Resources> 
    <Grid DataContext="{StaticResource userDataXmlDataProvider1}"> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="3*"/> 
     </Grid.RowDefinitions> 
     <TextBlock x:Name="BookRefTextBox" Grid.Row="0" Text="{Binding XPath=../@BookRef}" /> 
     <ListBox x:Name="listBox1" Grid.Row="1" 
       IsSynchronizedWithCurrentItem="True" 
       ItemsSource="{Binding}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal" Margin="8,0,8,0"> 
         <Label Content="{Binding [email protected]}" Width="100" Margin="5" /> 
        </StackPanel> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</Window> 

그리고 코드 뒤에서 BookRefTextBox의 텍스트를 가져올 수 있습니다.

편집 : XmlDataProviderWindow.Resources에 선언

경우, 당신은 키를 통해 리소스에 액세스하는 x:Key 속성이, 이름없는 : 뒤에 코드에서 소스를 설정하기 위해

.

XmlDataProvider xdp = this.Resources["userDataXmlDataProvider1"] as XmlDataProvider; 
xdp.Source = new Uri(...); 
+0

고마워, 그게 내가 원하는 것 같아. 그러나 나는 여기서 읽고있는 '기록'이 화면에 현재 표시된 것과 동기화되지 않을 것이라고 추측하고 있습니다. 그 추측에서는 맞습니까? 내 XML에는 여러 '책'과 여러 개의 '페이지'가 포함되어 있으며 현재 화면에 표시된 책에서 'BookRef'를 읽어야합니다. – RosieC

+0

와우, 그 질문은 간단하지 않다. 나는 Book 엘리먼트 (루트 엘리먼트) 만 있다고 생각했다. – kennyzx

+0

질문에 XML 샘플을 보여 주면 도움이 될 것입니다. – kennyzx