wpf
데이터 바인딩을 사용하여 사용자 지정 UserControls 만들기
수색…
비고
UserControl은 Control과 매우 다릅니다. 주요 차이점 중 하나는 UserControl이 XAML 레이아웃 파일을 사용하여 여러 개별 컨트롤을 배치 할 위치를 결정한다는 점입니다. 반면 컨트롤은 순수한 코드 일뿐입니다. 레이아웃 파일이 전혀 없습니다. 어떤면에서는 사용자 정의 컨트롤을 만드는 것이 사용자 정의 UserControl을 만드는 것보다 효과적 일 수 있습니다.
사용자 정의 기본 텍스트가있는 ComboBox
이 사용자 지정 UserControl은 일반 콤보 상자로 표시되지만 기본 제공 ComboBox 개체와 달리 아직 선택하지 않은 경우 사용자에게 기본 텍스트 문자열을 표시 할 수 있습니다.
이를 위해 UserControl은 두 개의 컨트롤로 구성됩니다. 분명히 실제 ComboBox가 필요하지만 일반 Label을 사용하여 기본 텍스트를 표시합니다.
CustomComboBox.xaml
<UserControl x:Class="UserControlDemo.CustomComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cnvrt="clr-namespace:UserControlDemo"
x:Name="customComboBox">
<UserControl.Resources>
<cnvrt:InverseNullVisibilityConverter x:Key="invNullVisibleConverter" />
</UserControl.Resources>
<Grid>
<ComboBox x:Name="comboBox"
ItemsSource="{Binding ElementName=customComboBox, Path=MyItemsSource}"
SelectedItem="{Binding ElementName=customComboBox, Path=MySelectedItem}"
HorizontalContentAlignment="Left" VerticalContentAlignment="Center"/>
<Label HorizontalAlignment="Left" VerticalAlignment="Center"
Margin="0,2,20,2" IsHitTestVisible="False"
Content="{Binding ElementName=customComboBox, Path=DefaultText}"
Visibility="{Binding ElementName=comboBox, Path=SelectedItem, Converter={StaticResource invNullVisibleConverter}}"/>
</Grid>
</UserControl>
보시다시피이 단일 UserControl은 실제로 두 개의 개별 컨트롤 그룹입니다. 이렇게하면 하나의 ComboBox만으로는 사용할 수없는 유연성이 생깁니다.
주목해야 할 몇 가지 중요한 사항이 있습니다.
- UserControl 자체에는
x:Name
집합이 있습니다. 이것은 코드 숨김에있는 속성에 바인딩하기를 원하기 때문입니다. 즉, 코드 자체를 참조 할 수있는 방법이 필요합니다. - ComboBox의 각 바인딩에는
ElementName
으로 UserControl의 이름이 있습니다. 이것은 UserControl이 바인딩을 찾기 위해 스스로를 인식 할 수 있도록하기위한 것입니다. - 라벨이 눈에 띄지 않습니다. 이것은 Label이 ComboBox의 일부임을 사용자에게 알리기위한 것입니다.
IsHitTestVisible=false
로 설정하면 사용자가 마우스를IsHitTestVisible=false
거나 라벨을 클릭하지 못하게됩니다. 모든 입력은 아래의 ComboBox로 전달됩니다. - Label은
InverseNullVisibility
변환기를 사용하여 표시 여부를 결정합니다. 이 코드의 하단에이 코드가 있습니다.
CustomComboBox.xaml.cs
public partial class CustomComboBox : UserControl
{
public CustomComboBox()
{
InitializeComponent();
}
public static DependencyProperty DefaultTextProperty =
DependencyProperty.Register("DefaultText", typeof(string), typeof(CustomComboBox));
public static DependencyProperty MyItemsSourceProperty =
DependencyProperty.Register("MyItemsSource", typeof(IEnumerable), typeof(CustomComboBox));
public static DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(CustomComboBox));
public string DefaultText
{
get { return (string)GetValue(DefaultTextProperty); }
set { SetValue(DefaultTextProperty, value); }
}
public IEnumerable MyItemsSource
{
get { return (IEnumerable)GetValue(MyItemsSourceProperty); }
set { SetValue(MyItemsSourceProperty, value); }
}
public object MySelectedItem
{
get { return GetValue(MySelectedItemProperty); }
set { SetValue(MySelectedItemProperty, value); }
}
}
코드 숨김에서 우리는이 UserControl을 사용하여 프로그래머가 사용할 수있는 속성을 단순히 노출하고 있습니다. 불행히도이 클래스 외부에서 ComboBox에 직접 액세스 할 수 없으므로 중복 속성 (예 : ComboBox의 ItemsSource
에 대한 MyItemsSource
을 노출해야합니다. 그러나 이것은 네이티브 컨트롤과 유사하게 사용할 수 있다는 점을 고려할 때 약간의 단점이 있습니다.
CustomComboBox
UserControl을 사용하는 방법은 다음과 같습니다.
<Window x:Class="UserControlDemo.UserControlDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cntrls="clr-namespace:UserControlDemo"
Title="UserControlDemo" Height="240" Width=200>
<Grid>
<cntrls:CustomComboBox HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="165"
MyItemsSource="{Binding Options}"
MySelectedItem="{Binding SelectedOption, Mode=TwoWay}"
DefaultText="Select an option..."/>
<Grid>
</Window>
그리고 최종 결과 :
다음은 InverNullVisibilityConverter가 UserControl의 Label에 필요한 기능입니다. 이 버전 은 lll의 버전을 약간 변형 한 것입니다.
public class InverseNullVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}