@dimohy 관심 갖아주셔서 감사드립니다. 제가 사내망으로 간간이 시간날 때마다 공부겸 진행하는거라 오픈 깃을 통해 공유드리지 못할 것 같아요. 대신 관련 코드를 이곳에 공유드리겠습니다. 우선, 원인은 찾았는데 관련해서 방법을 아직 찾지 못해 고민 중입니다.
앞서 말해드린대로 해당 페이지의 TabControl 안에 있는 Combobox
를 선택하고 Search
버튼을 누르면, 결과 정보가 FileInitialListup
UserControl로 호출되는 방식입니다. 그리고 Reset
버튼을 누르면 해당 결과 정보가 초기화될 예정입니다.
<Page x:Class="WPF_ParsingXML.View.FilePage"
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"
xmlns:local="clr-namespace:WPF_ParsingXML.View"
xmlns:vm="clr-namespace:WPF_ParsingXML.ViewModels"
xmlns:uc="clr-namespace:WPF_ParsingXML.View.FileSubPages.UserControls"
mc:Ignorable="d"
d:DesignHeight="550"
d:DesignWidth="800"
Title="FilePage">
<Page.Resources>
<vm:FileVM x:Key="vm" />
<Style x:Key="CheckBoxOneClick" />
</Page.Resources>
<DockPanel DataContext="{StaticResource vm}">
<StackPanel Orientation="Vertical"
Width="700">
<TabControl x:Name="FileTabControl"
Visibility="Visible"
SelectedIndex="{Binding SelectedTabIndex, Mode=TwoWay}">
<TabItem Header="Search"
Name="SearchTab">
<StackPanel>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="10">
<ComboBox x:Name="ComboModel"
Width="150"
Height="20"
ItemsSource="{Binding filterings}"
SelectedItem="{Binding SelectedFiltering}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ModelName}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Content="Search"
Margin="10"
FontSize="15"
x:Name="Btn_Search"
Command="{Binding fileSearchCommand}"
CommandParameter="{Binding SelectedFiltering}"
Cursor="Hand" />
<Button Content="Reset"
FontSize="15"
Cursor="Hand"
x:Name="Btn_Reset"
Command="{Binding resetCommand}"
Width="80" />
</StackPanel>
<ScrollViewer Name="SearchScrollViewer"
Margin="10">
<uc:FileInitialListup Visibility="Visible" />
</ScrollViewer>
</StackPanel>
</TabItem>
</TabControl>
</StackPanel>
</DockPanel>
</Page>
FileInitialListup
UserControl에서는 체크박스를 통해서 전체 혹은 일부 목록만을 선택을 할 수 있도록 하기 위해서 첫번째 Column에는 체크박스 관련 로직이 포함되어 있습니다.
<UserControl x:Class="WPF_ParsingXML.View.FileSubPages.UserControls.FileInitialListup"
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"
xmlns:local="clr-namespace:WPF_ParsingXML.View.FileSubPages.UserControls"
xmlns:bp="clr-namespace:WPF_ParsingXML.ViewModels.Base"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="500">
<UserControl.Resources>
<bp:BindingProxy x:Key="proxy" Data="{Binding}" />
<Style x:Key="CheckBoxOneClick" />
</UserControl.Resources>
<DataGrid Name="fileList"
ItemsSource="{Binding Files}"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalAlignment="Center"
AutoGenerateColumns="False"
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.Columns>
<DataGridCheckBoxColumn x:Name="xCheckBox"
Binding="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ElementStyle="{StaticResource CheckBoxOneClick}"
Width="30"
MinWidth="30">
<DataGridCheckBoxColumn.Header>
<CheckBox x:Name="xSelectAll"
IsChecked="{Binding Data.Files.IsSelectAll, Source={StaticResource proxy} }" />
</DataGridCheckBoxColumn.Header>
</DataGridCheckBoxColumn>
<DataGridTextColumn Header="FileName"
Binding="{Binding FileName}"
Width="1*" />
<DataGridTextColumn Header="Modified Date"
Binding="{Binding Modified}"
Width="1*" />
<DataGridTextColumn Header="Size"
Binding="{Binding Size, StringFormat={}{0} MB}"
Width="1*" />
</DataGrid.Columns>
</DataGrid>
</UserControl>
아래는 VM입니다.
namespace WPF_ParsingXML.ViewModels
{
public class FileVM : INotifyPropertyChanged
{
#region Propertites
private IXMLHelper _XMLHelper;
public ICommand fileSearchCommand { get; private set; }
public ICommand resetCommand { get; private set; }
public List<Filtering> filterings { get; set; }
public SelectableCollection<File> Files { get; set; } = new SelectableCollection<File>();
private Filtering _selectedFiltering;
public Filtering SelectedFiltering
{
get { return _selectedFiltering; }
set
{
_selectedFiltering = value;
Files.Clear();
OnPropertyChanged(nameof(SelectedFiltering));
}
}
private SelectableCollection<File> _selectedFiles;
public SelectableCollection<File> SelectedFiles
{
get { return _selectedFiles; }
set
{
_selectedFiles = value;
OnPropertyChanged(nameof(SelectedFiles));
}
}
private int _selectedTabIndex = 0;
public int SelectedTabIndex
{
get { return _selectedTabIndex; }
set { _selectedTabIndex = value; OnPropertyChanged(nameof(SelectedTabIndex)); }
}
#endregion
/// <summary>
/// Constructor
/// </summary>
public FileVM()
{
InitProcess();
}
private void InitProcess()
{
_downloadHelper = new DownloadHelper();
_XMLHelper = new XMLHelper();
fileSearchCommand = new RelayCommand<object>(GetFileList);
resetCommand = new RelayCommand<object>(ResetInfo);
filterings = new List<Filtering>();
CreateFiltering();
}
private void CreateFiltering()
{
filterings.Add(new Filtering { ModelName = "Book" });
filterings.Add(new Filtering { ModelName = "Article" });
filterings.Add(new Filtering { ModelName = "News" });
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public void GetFileList(object filter)
{
if (Files.Count != 0)
{
return;
}
//IsClickedSearch = false;
var filtering = filter as Filtering;
var intialListFile = _XMLHelper.ParseXML_Sample2();
foreach (var sw in intialListFile)
{
Files.Add(sw);
}
}
private void ResetInfo(object ojb)
{
SelectedTabIndex = 0;
// Clean up: Freezable로 인해 Files가 초기화 안됨.
Files = null;
SelectedFiles = null;
FolderPath = null;
}
}
}
문제가 발생한 부분은 FileInitialListup
UserControl에서 사용된 Freezable 때문이었습니다. 일전에 <CheckBox x:Name="xSelectAll" IsChecked="{Binding Data.Files.IsSelectAll, Source={StaticResource proxy} }" />
TabControl에서 RelativeSource FindAncestor
모드가 적용이 되지 않았습니다. 그래서 관련 자료를 찾다가 Freezable 알게 되서 우선 적용해보았습니다.
using System.Windows;
namespace WPF_ParsingXML.ViewModels.Base
{
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy), new UIPropertyMetadata(null));
}
}
하지만 이로 인해, VM에서 Reset버튼으로 초기화해도 기존 정보를 갖고 있게 되는 것입니다. VM에서 정보가 변경되면 Freezable에서 업데이트를 해주면 좋을 것 같은데… 조언을 부탁드립니다.