WPF에서의 바인딩을 위한 내부 제어 속성 노출
[편집] : 나 혼자 할 수 있는 방법 알아냈어.저는 다른 누군가가 며칠 동안 구글링을 할 수 있기를 바라며 제 해결책을 올렸습니다.만약 당신이 WPF의 전문가라면, 제 솔루션을 보시고, 더 나은/더 우아한/더 효율적인 방법이 있는지 알려주세요.특히, 나는 내가 모르는 것을 알고 싶다.이 해결책이 어떻게 저를 파멸시킬까요?문제는 내부 제어 특성을 노출시키는 것으로 요약됩니다.
문제:XML 파일의 WPF에서 데이터 바인딩 GUI를 자동 생성하기 위한 코드를 만들고 있습니다.노드 유형 등을 판별하는 데 도움이 되는 xsd 파일이 있습니다.간단한 키/밸류 요소는 간단합니다.
이 요소를 해석할 때:
<Key>value</Key>
새로운 'KeyValueControl'을 생성하여DataContext
이 요소로 이동합니다.그KeyValueControl
로 정의됩니다.UserControl
간단한 바인딩이 붙어있을 뿐이죠심플한 XElement에 매우 적합합니다.
이 컨트롤 내부의 XAML은 다음과 같습니다.
<Label Content={Binding Path=Name} />
<TextBox Text={Binding Path=Value} />
그 결과 요소 이름이 포함된 라벨과 편집할 수 있는 값이 포함된 텍스트 상자가 있는 라인이 생성됩니다.
현재 실제 값이 아닌 조회 값을 표시해야 할 경우가 있습니다.위와 같은 'Key Value Combo Box'를 만들고 싶습니다.KeyValueControl
(파일의 정보에 근거해) 를 지정할 수 있습니다.ItemsSource
,DisplayMemberPath
,그리고.ValueMemberPath
. 'DisplayMemberPath' 및 'ValueMemberPath' 바인딩은 다음과 같습니다.KeyValueControl
.
표준 사용자 컨트롤로 이 작업을 처리할 수 있는지, 또는 다음 사용자 컨트롤에서 상속해야 하는지 알 수 없습니다.Selector
.
컨트롤의 XAML은 다음과 같습니다.
<Label Content={Binding Path=Name} />
<ComboBox SelectedValue={Binding Path=Value}
ItemsSource={Binding [BOUND TO THE ItemsSource PROPERTY OF THIS CUSTOM CONTROL]
DisplayMemberPath={Binding [BOUND TO THE DisplayMemberPath OF THIS CUSTOM CONTROL]
SelectedValuePath={Binding [BOUND TO THE SelectedValuePath OF THIS CUSTOM CONTROL]/>
코드로 다음과 같은 작업을 수행합니다(이 노드가 'Thing'이며 사용자가 ID를 선택할 수 있도록 사물 목록을 표시해야 합니다).
var myBoundComboBox = new KeyValueComboBox();
myBoundComboBox.ItemsSource = getThingsList();
myBoundComboBox.DisplayMemberPath = "ThingName";
myBoundComboBox.ValueMemberPath = "ThingID"
myBoundComboBox.DataContext = thisXElement;
...
myStackPanel.Children.Add(myBoundComboBox)
그래서 질문하겠습니다.
1) 내 것을 상속해야 하는가?KeyValueComboBox
부터Control
또는Selector
?
2) 에서 상속을 받아야 하는 경우Control
, 내부 콤보 박스를 공개하려면 어떻게 해야 합니까?ItemsSource
,DisplayMemberPath
,그리고.ValueMemberPath
바인딩을 위해?
3) Selector에서 상속을 받아야 할 경우, 어떻게 시작할 수 있는지에 대한 간단한 예를 제시해 주실 수 있습니까?저는 WPF에 처음 참여하기 때문에 WPF가 필요한 길이라면 간단하고 좋은 예시를 들 수 있습니다.
나 혼자 이걸 어떻게 해야 할지 고민하게 됐어.다른 사람들이 효과적인 솔루션을 볼 수 있도록 여기에 답을 게시합니다. WPF 전문가가 방문하여 더 나은/더 우아한 방법을 보여 줄 것입니다.
그래서 정답은 2번이 되었습니다.내부 특성을 드러내는 것이 정답입니다.설치하는 건 사실 꽤 쉬워요.어떻게 하는지 알게 되면요(찾을 수 있는) 완전한 예는 많지 않기 때문에 이 문제가 발생한 다른 사람에게 도움이 되었으면 합니다.
ComboBoxWithLabel.xaml.cs
Dependency Properties 이 、 Dependency Properties 。가 하고 있는 은 단지에 주의하세요.LabelContent
★★★★★★★★★★★★★★★★★」ItemsSource
을 이러한 속성에 합니다.) XAML은 내부 컨트롤의 속성을 처리합니다.
namespace BoundComboBoxExample
{
/// <summary>
/// Interaction logic for ComboBoxWithLabel.xaml
/// </summary>
public partial class ComboBoxWithLabel : UserControl
{
// Declare ItemsSource and Register as an Owner of ComboBox.ItemsSource
// the ComboBoxWithLabel.xaml will bind the ComboBox.ItemsSource to this
// property
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty ItemsSourceProperty =
ComboBox.ItemsSourceProperty.AddOwner(typeof(ComboBoxWithLabel));
// Declare a new LabelContent property that can be bound as well
// The ComboBoxWithLable.xaml will bind the Label's content to this
public string LabelContent
{
get { return (string)GetValue(LabelContentProperty); }
set { SetValue(LabelContentProperty, value); }
}
public static readonly DependencyProperty LabelContentProperty =
DependencyProperty.Register("LabelContent", typeof(string), typeof(ComboBoxWithLabel));
public ComboBoxWithLabel()
{
InitializeComponent();
}
}
}
Combo Box With Label.xaml
과 XAML의 하고 매우 ComboBox
ItemsSource
이러한 바인딩을 올바르게 하는 가장 쉬운 방법은 위와 같이 .cs 파일에서 속성을 선언하고 VS2010 디자이너를 사용하여 속성 페인으로 바인딩 소스를 설정하는 것입니다.본질적으로, 이것이 내가 아는 유일한 방법이야 내부 컨트롤의 속성을 베이스 컨트롤에 결합시킬 수 있는.더 좋은 방법이 있으면 알려주세요.
<UserControl x:Class="BoundComboBoxExample.ComboBoxWithLabel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="28" d:DesignWidth="453" xmlns:my="clr-namespace:BoundComboBoxExample">
<Grid>
<DockPanel LastChildFill="True">
<!-- This will bind the Content property on the label to the 'LabelContent'
property on this control-->
<Label Content="{Binding Path=LabelContent,
RelativeSource={RelativeSource FindAncestor,
AncestorType=my:ComboBoxWithLabel,
AncestorLevel=1}}"
Width="100"
HorizontalAlignment="Left"/>
<!-- This will bind the ItemsSource of the ComboBox to this
control's ItemsSource property -->
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType=my:ComboBoxWithLabel,
AncestorLevel=1},
Path=ItemsSource}"></ComboBox>
<!-- you can do the same thing with SelectedValuePath,
DisplayMemberPath, etc, but this illustrates the technique -->
</DockPanel>
</Grid>
</UserControl>
Main Window.xaml
원하던 바로 그 XAML입니다.이렇게 .ItemsSource
및LabelContent
WPF를 사용하다
<Window x:Class="BoundComboBoxExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="86" Width="464" xmlns:my="clr-namespace:BoundComboBoxExample"
Loaded="Window_Loaded">
<Window.Resources>
<ObjectDataProvider x:Key="LookupValues" />
</Window.Resources>
<Grid>
<my:ComboBoxWithLabel LabelContent="Foo"
ItemsSource="{Binding Source={StaticResource LookupValues}}"
HorizontalAlignment="Left"
Margin="12,12,0,0"
x:Name="comboBoxWithLabel1"
VerticalAlignment="Top"
Height="23"
Width="418" />
</Grid>
</Window>
완전성에 대해서는, MainWindow.xaml.cs 를 참조해 주세요.
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
((ObjectDataProvider)FindResource("LookupValues")).ObjectInstance =
(from i in Enumerable.Range(0, 5)
select string.Format("Bar {0}", i)).ToArray();
}
}
저는 당신의 해결책을 시도했지만 실패했습니다.이 값은 내부 컨트롤에 전혀 전달되지 않습니다.이렇게 외부 제어에서 동일한 종속성 속성을 선언하고 내부와 외부로 바인드했습니다.
// Declare IsReadOnly property and Register as an Owner of TimePicker (base InputBase).IsReadOnly the TimePickerEx.xaml will bind the TimePicker.IsReadOnly to this property
// does not work: public static readonly DependencyProperty IsReadOnlyProperty = InputBase.IsReadOnlyProperty.AddOwner(typeof(TimePickerEx));
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register("IsReadOnly", typeof (bool), typeof (TimePickerEx), new PropertyMetadata(default(bool)));
public bool IsReadOnly
{
get { return (bool) GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
xaml에서보다 높음:
<UserControl x:Class="CBRControls.TimePickerEx" x:Name="TimePickerExControl"
...
>
<xctk:TimePicker x:Name="Picker"
IsReadOnly="{Binding ElementName=TimePickerExControl, Path=IsReadOnly}"
...
/>
</UserControl>
언급URL : https://stackoverflow.com/questions/4169090/exposing-inner-control-properties-for-binding-in-wpf
'source' 카테고리의 다른 글
iOS UIView 컨트롤러의 라이프 사이클을 이해하려고 합니다. (0) | 2023.04.12 |
---|---|
bash 스크립트가 실행 중일 때 출력을 파일로 강제 플러시합니다. (0) | 2023.04.12 |
여러 개의 수식 키를 사용한WPF에서의 KeyBinding 작성 (0) | 2023.04.12 |
C#을 사용하여 Excel 파일의 데이터를 읽는 방법 (0) | 2023.04.12 |
EXISTES를 직접 선택할 수 있습니까? (0) | 2023.04.07 |