2011-02-18 8 views
0

두 개의 텍스트 상자 컨트롤에 목록 상자의 SelectedItem 속성을 바인딩하려고합니다. 이러한 컨트롤은 Windows 리소스 섹션에 있습니다. 아이디어는 목록 상자의 항목이 선택되면 두 개의 텍스트 상자 컨트롤이 내 사용자 정의 클래스에서 "blockName"및 "blockHelpText"를 표시합니다. but1 버튼을 클릭하여 목록 상자를 먼저로드합니다.데이터 바인딩이 리소스 사전 내에서 작동하지 않습니다.

<Window.Resources> 
<StackPanel x:Key="testsp" Visibility="Visible" DataContext="{Binding ElementName=lsbCommonBlocks, Path=SelectedItem, diagnostics:PresentationTraceSources.TraceLevel=High}"> 
     <ListBox x:Name="lsbCommonBlocks" DisplayMemberPath="BlockName" SelectionChanged="lb_sc"/> 
     <Button x:Name="but1" Click="but1_click" Content="Button 1"/> 
     <TextBox x:Name="txt1" Text="{Binding Path=BlockName, diagnostics:PresentationTraceSources.TraceLevel=High}"/> 
     <TextBox x:Name="txt2" Text="{Binding Path=BlockHelpText, diagnostics:PresentationTraceSources.TraceLevel=High}"/> 
    </StackPanel> 
</Window.Resources> 
<Grid> 
    <ContentControl Visibility="Visible" x:Name="contentWorkArea" Content="{StaticResource testsp}"/> 
</Grid> 

클릭 이벤트는 목록 상자의 Itemsources 속성을 내 사용자 지정 클래스 BlockToolBar에 연결합니다.

BlockToolBar[] blocks = { new BlockToolBar("Block 1", "No help for this block."), 
           new BlockToolBar("Block 2", "Help."), 
           new BlockToolBar("Block 3", "Help again.") }; 

private void but1_click(object sender, RoutedEventArgs e) 
    { 
     StackPanel sp = (StackPanel)this.TryFindResource("testsp"); 
     ListBox lb = (ListBox)LogicalTreeHelper.FindLogicalNode(sp, "lsbCommonBlocks"); 
     lb.ItemsSource = blocks; 
    } 

public class BlockToolBar : INotifyPropertyChanged 
{ 
    private string blockName; 
    public string BlockName 
    { 
     get { return blockName; } 
     set { 
      blockName = value; 
      OnPropertyChanged(new PropertyChangedEventArgs("BlockName")); 
     } 
    } 

    private string blockHelpText; 
    public string BlockHelpText 
    { 
     get { return blockHelpText; } 
     set { 
      blockHelpText = value; 
      OnPropertyChanged(new PropertyChangedEventArgs("BlockHelpText")); 
     } 
    } 

    public BlockToolBar() 
    { 
     blockName = ""; 
     blockHelpText = ""; 
    } 

    public BlockToolBar(string BlockName, string BlockHelpText) 
    { 
     blockName = BlockName; 
     blockHelpText = BlockHelpText; 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, e); 
    } 
} 

데이터 바인딩이 작동하지 않습니다. 단추를 클릭하면 TextBox의 txt1 및 txt2가 비어 있습니다. 목록 상자에 ok가 입력됩니다. 목록 상자에 이벤트를 만들어서 BlockToolBar 속성을 가져올 수 있음을 확인했습니다.

Visual Studio (express) 출력 창이 다음과 같이 표시됩니다. System.Windows.Data 오류 : 4 : 'ElementName = lsbCommonBlocks'참조로 바인딩 소스를 찾을 수 없습니다. BindingExpression : Path = SelectedItem; DataItem = null; 대상 요소는 'StackPanel'입니다 (Name = ''); 대상 속성이 'DataContext'(유형 '개체')

내가 잘못하고 있는지 확실하지 않습니다. 나는 WPF에 처음 접해 보았습니다.

stackpanel 리소스 (testsp)를 제거하고 contentcontrol을 testsp 컨트롤로 바꾸면 데이터 바인딩이 작동합니다. 또한 리소스의 BlockToolBar 개체에 직접 txt1 및 txt2를 바인딩 할 수 있지만 리소스에있는 경우 selecteditem에 txt1/txt2를 바인딩 할 수 없습니다.

내가 이것을하고있는 이유는 내가 분리 된 자원 창고에 들어가서 contentcontrols를 통해 나의 메인 윈도우를 부르는 복잡한 메인 윈도우를 가지고 있기 때문이다. 내가 그 일을 할 수 없을 때 나는 나의 문제를 좁히려 고 노력하는 더 간단한 프로젝트를 만든다.

답변

0

코드에서 바인딩을 만들어야하는 것처럼 보입니다. 나는 다음과 같은 변경을했고 효과가 있었다. 생각 해보니 전에 이걸 시도해 봤는데 ...

private void but1_click(object sender, RoutedEventArgs e) 
    { 
     StackPanel sp = (StackPanel)this.TryFindResource("testsp"); 
     ListBox lb = (ListBox)LogicalTreeHelper.FindLogicalNode(sp, "lsbCommonBlocks"); 

     Binding myBinding = new Binding(); 
     myBinding.Source = lb; 
     myBinding.Path = new PropertyPath("SelectedItem"); 
     sp.SetBinding(StackPanel.DataContextProperty, myBinding); 

     lb.ItemsSource = blocks; 

    } 
관련 문제