2024. 1. 4. 10:57
Programming/WPF
개발환경
OS : Window 10 x64 ver.22H2
DevTool : VS2019 ver.16.11.29
Framework : .NET Framework 4.8
Other : DevExpress 22.2
ScrollViewer에 ListBox를 배치하고 동적으로 CustomControl을 생성 및 삭제 하는 방법에 대한 글임.
CustromControl은 Label을 2개 가지고 있는 Control이며, MultiTrigger를 사용해서 Selected, Focused Conditions을 추가함
WPF MVVM 패턴을 사용함.
View.xaml
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ListBox Width="320" Height="400" BorderThickness="0"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding ItemCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{StaticResource BorderBrushColor}"
CornerRadius="5" Height="50" Margin="0,5,0,5"
Name="Bd" SnapsToDevicePixels="True">
<ContentPresenter x:Name="content" Content="{TemplateBinding ContentControl.Content}"
ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="Selector.IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Panel.Background" TargetName="Bd" Value="{StaticResource TwoLableBGColor_mouseOver}"/>
<Setter Property="Border.BorderBrush" TargetName="Bd" Value="Transparent"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="Selector.IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Panel.Background" TargetName="Bd" Value="{StaticResource TwoLableBGColor_checked}"/>
<Setter Property="Foreground" Value="{StaticResource TwoLableFontColor_checked}"/>
<Setter Property="Border.BorderBrush" TargetName="Bd" Value="Transparent"/>
</MultiTrigger>
<Trigger Property="UIElement.IsMouseOver" Value="True">
<Setter Property="Panel.Background" TargetName="Bd" Value="{StaticResource TwoLableBGColor_mouseOver}"/>
<Setter Property="Foreground" Value="{StaticResource TwoLableFontColor_checked}"/>
<Setter Property="Border.BorderBrush" TargetName="Bd" Value="Transparent"/>
</Trigger>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd">
<Setter.Value>
<DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommand EventName="SelectionChanged" Command="{Binding SelectedButtonCommand}" CommandParameter="{Binding SelectedItem}"/>
</dxmvvm:Interaction.Behaviors>
</ListBox>
</ScrollViewer>
ViewModel.cs
View의 DataContext Class
public class ViewModel
{
public ObservableCollection<TwoLabel> ItemCollection { get; set; }
public int SelectedIndex
{
get => GetValue<int>();
set => SetValue(value);
}
public object SelectedItem
{
get => GetValue<object>();
set => SetValue(value);
}
public ICommand ButtonCommand => new DelegateCommand<object>(ButtonCommandMethod);
public ICommand<object> SelectedButtonCommand => new DelegateCommand<object>(SelectedButtonCommandMethod);
public PamProUserViewModel()
{
ItemCollection = new ObservableCollection<PamProTwoLabel>();
}
private void ButtonCommandMethod(object obj)
{
string param = obj as string;
switch (param)
{
case "add": AddUserButtonCommandMethod(); break;
default: break;
}
}
private void AddUserButtonCommandMethod()
{
TwoLabel button = new TwoLabel()
{
ButtonCode = DateTime.Now.ToString(),
TextTitle = "Operator",
TextDescription = "Description"
};
button.SetText("Operator", "Description");
ItemCollection.Add(button);
}
private void SelectedButtonCommandMethod(object obj)
{
if (obj is TwoLabel button)
{
string code = button.ButtonCode;
for (int i = 0; i < ItemCollection.Count; i++)
{
if (ItemCollection[i].ButtonCode == code)
{
ItemCollection[i].SetForeground("select");
}
else
{
ItemCollection[i].SetForeground("unSelect");
}
}
}
}
}
CustomControl TwoLabel
namespace CommonControls.Views
{
[ToolboxItem(true)]
public class TwoLabel : Label, INotifyPropertyChanged
{
#region properties
[Category("버튼코드"), Description("용어코드")]
public string ButtonCode { get; set; }
[Category("TextTitle"), Description("지정할 텍스트")]
public string TextTitle { get; set; }
[Category("TextDescription"), Description("버튼 설명")]
public string TextDescription { get; set; }
#endregion
#region Layout Controls
private TextBlock descriptionTextBlock;
public TextBlock DescriptionTextBlockControl
{
get => descriptionTextBlock;
set
{
descriptionTextBlock = value;
OnPropertyChangedMethod("DescriptionTextBlockControl");
}
}
private TextBlock titleTextBlock;
public TextBlock TitleTextBlockControl
{
get => titleTextBlock;
set
{
titleTextBlock = value;
OnPropertyChangedMethod("TitleTextBlockControl");
}
}
#endregion
public TwoLabel() : base()
{
SetDefaultProperties();
CreateContent();
CreateStyle();
}
public event PropertyChangedEventHandler PropertyChanged;
// Set default properties of PamProIconDescriptionButton
private void SetDefaultProperties()
{
HorizontalContentAlignment = HorizontalAlignment.Stretch;
VerticalContentAlignment = VerticalAlignment.Center;
Loaded += OnLoaded;
}
private void OnPropertyChangedMethod([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// IconDescriptionButton Style setting
private void CreateStyle()
{
Height = 50;
MinWidth = 200;
Margin = new Thickness(0, 5, 0, 5);
Background = new SolidColorBrush(Colors.Transparent);
BorderThickness = new Thickness(0);
BorderBrush = new SolidColorBrush(Colors.Transparent);
VerticalAlignment = VerticalAlignment.Center;
}
// Create the IconDescriptionButton Content layout
private void CreateContent()
{
StackPanel rootStackPanel = CreateStackPanel();
TitleTextBlockControl = CreateTitleLabelContent();
DescriptionTextBlockControl = CreateDescLabelContent();
_ = rootStackPanel.Children.Add(TitleTextBlockControl);
_ = rootStackPanel.Children.Add(DescriptionTextBlockControl);
Content = rootStackPanel;
}
// Create title Label control
private TextBlock CreateTitleLabelContent()
{
TextBlock titleLabel = new TextBlock
{
Width = 80,
FontSize = 20,
FontWeight = FontWeights.Bold,
Foreground = Brushes.Black,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Left,
Margin = new Thickness(6, 0, 0, 0)
};
return titleLabel;
}
// Create StackPanel controls (root, branch)
private StackPanel CreateStackPanel()
{
StackPanel stackPanel = new StackPanel
{
VerticalAlignment = VerticalAlignment.Center,
Background = Brushes.Transparent
};
stackPanel.Orientation = Orientation.Horizontal;
return stackPanel;
}
// Craete description Label control
private TextBlock CreateDescLabelContent()
{
TextBlock descLabel = new TextBlock
{
FontSize = 12,
TextWrapping = TextWrapping.Wrap,
Foreground = Brushes.Black,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Stretch,
Margin = new Thickness(15, 0, 0, 0)
};
return descLabel;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
TitleTextBlockControl.Text = TextTitle;
DescriptionTextBlockControl.Text = TextDescription;
}
public void SetText(string _title, string _desc)
{
if (_title != null && !_title.Equals(""))
{
TitleTextBlockControl.Text = _title;
TextTitle = _title;
}
if (_desc != null && !_desc.Equals(""))
{
DescriptionTextBlockControl.Text = _desc;
TextDescription = _desc;
}
}
public void SetForeground(string isSelection)
{
if (isSelection.Equals("select"))
{
DescriptionTextBlockControl.Foreground = new SolidColorBrush(Colors.White);
TitleTextBlockControl.Foreground = new SolidColorBrush(Colors.White);
}
else
{
DescriptionTextBlockControl.Foreground = new SolidColorBrush(Colors.Black);
TitleTextBlockControl.Foreground = new SolidColorBrush(Colors.Black);
}
}
}
}
'Programming > WPF' 카테고리의 다른 글
[WPF, C#] Canvas에 TextBlock 생성, Drag & Drop Event 구현 (0) | 2024.01.04 |
---|---|
[WPF, C#] Array.Copy() - byte 복사 (0) | 2023.02.17 |
[WPF] UniformGrid에 동적으로 Button 생성하고 Button 속성값 변경하기 (2) | 2021.11.24 |
[WPF] Window 타이틀바 없애기 (0) | 2020.12.15 |
[WPF] MediaElement 동영상 무한재생 (0) | 2020.12.14 |