Neredeyse ikna olduğum için çok tuhaf bir sorunum var.Bir UserControl örneğindeki UserControl kaynağının başka bir örnekle senkronize edilmesi
Üç UserControl'im var, FolderView, LocalFolderView, RemoteFolderView. LocalFolderView ve RemoteFolderView, her ikisi de FolderView'ı devralır ve sırasıyla LocalExplorer ve RemoteExplorer olmak üzere iki farklı denetimde kullanılır.
LocalExplorer/RemoteExplorer, FolderView'a bağlandığım dizelerin bir listesini içerir.
1'den fazla örneğim LocalExplorer/RemoteExplorer'ım olduğunda, her iki Gezgin için de FolderView'daki ListBox aynı öğeleri gösterir, ancak denetimlerin bağımlılık özellikleri farklıdır.
Kod gerçekten çok uzun olduğu için, olabildiğince yoğunlaşmaya çalışacağım. Şu anda, sorunun konulara bağlandığım gibi olduğuna inanıyorum.
LocalExplorer.xaml (RemoteExplorer.xaml özdeş bir yol izler,):
<UserControl x:Class="LocalExplorer"
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:MyNamespace"
mc:Ignorable="d"
Width="Auto"
Height="Auto"
ClipToBounds="True"
x:Name="explorer">
<local:ExplorerBase Path="{Binding ElementName=explorer, Path=Path}" Orientation="{Binding ElementName=explorer, Path=Orientation}">
<local:ExplorerBase.FolderView>
<local:LocalFolderView x:Name="FolderView" Path="{Binding Path, RelativeSource={RelativeSource AncestorType={x:Type local:LocalExplorer}}}"/>
</local:ExplorerBase.FolderView>
</local:ExplorerBase>
</UserControl>
LocalExplorer.xaml.cs (RemoteExplorer
Burada bu birden fazla, örneğin hata sergiler sahip kontrol imkanı sağlamaktadır. xaml.cs) benzer bir yol izler:
public partial class Explorer : UserControl
{
#region Explorer
public Explorer()
{
InitializeComponent();
}
#endregion
#region Dependency Properties
public static DependencyProperty PathProperty = DependencyProperty.Register("Path", typeof(string), typeof(Explorer), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Path
{
get
{
return (string)GetValue(PathProperty);
}
set
{
SetValue(PathProperty, value);
}
}
#endregion
}
Sonraki tüm kaşifler özgü UI mantık ev ExplorerBase gibidir:
ExplorerBase.cs:
public partial class ExplorerBase : Control
{
public ExplorerBase()
{
this.DefaultStyleKey = typeof(ExplorerBase);
}
public override void OnApplyTemplate()
{
base.ApplyTemplate();
}
public static readonly DependencyProperty FolderViewProperty = DependencyProperty.Register("FolderView", typeof(object), typeof(ExplorerBase), null);
public object FolderView
{
get
{
return GetValue(FolderViewProperty);
}
set
{
SetValue(FolderViewProperty, value);
}
}
public static DependencyProperty PathProperty = DependencyProperty.Register("Path", typeof(string), typeof(ExplorerBase), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Path
{
get
{
return (string)GetValue(PathProperty);
}
set
{
SetValue(PathProperty, value);
}
}
}
I/Generic.xaml yaklaşım Temalar kullanarak şablon:
<Style TargetType="{x:Type Imagin.Controls:ExplorerBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Imagin.Controls:ExplorerBase">
<ContentPresenter Content="{TemplateBinding FolderView}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Ve son olarak, ben hata neler olduğuna inanıyoruz FolderView. FolderView, kullanılan gerçek denetimler, LocalFolderView ve RemoteFolderView için bir temel oluşturur. Not, her iki LocalExplorer ve RemoteExplorer kullanmam veya kullanmamamdan bağımsız olarak hata oluşur. Aynı anda sadece iki örneği test ettim.
FolderView.xaml:
<UserControl x:Class="FolderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Height="Auto"
Width="Auto"
x:Name="folderView">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
<Imagin.Data:InverseBooleanToVisibilityConverter x:Key="InverseBoolToVisibility" />
<Grid>
<ListBox x:Name="ListBox" AllowDrop="True" ItemsSource="{Binding Path=Items, RelativeSource={RelativeSource AncestorType={x:Type local:FolderView}}}" SelectionMode="Extended" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" IsSynchronizedWithCurrentItem="True">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:BindableFile}">
<local:Thumbnail FilePath="{Binding Path}" IsCheckBoxEnabled="False" ToolTip="{Binding ToolTip}" Title="{Binding Name}" Width="Auto" Height="Auto"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:BindableFolder}">
<local:Thumbnail FilePath="{Binding Path}" IsCheckBoxEnabled="False" ToolTip="{Binding ToolTip}" Title="{Binding Name}" Width="Auto" Height="Auto"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<DataGrid x:Name="DataGrid" ItemsSource="{Binding Items, RelativeSource={RelativeSource AncestorType={x:Type local:FolderView}}}" AutoGenerateColumns="False" BorderThickness="0" AlternationCount="2" GridLinesVisibility="None" HeadersVisibility="Column" CanUserAddRows="False" CanUserResizeColumns="True" IsSynchronizedWithCurrentItem="True" AllowDrop="True">
</DataGrid>
</Grid>
</UserControl>
FolderView.xaml.cs:
public abstract partial class FolderView : UserControl
{
#region DependencyProperties
public static DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<BindablePath>), typeof(FolderView), new FrameworkPropertyMetadata(new ObservableCollection<BindablePath>(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public ObservableCollection<BindablePath> Items
{
get
{
return (ObservableCollection<BindablePath>)GetValue(ItemsProperty);
}
set
{
SetValue(ItemsProperty, value);
}
}
public static DependencyProperty PathProperty = DependencyProperty.Register("Path", typeof(string), typeof(FolderView), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnPathChanged));
public string Path
{
get
{
return (string)GetValue(PathProperty);
}
set
{
SetValue(PathProperty, value);
}
}
private static void OnPathChanged(DependencyObject Object, DependencyPropertyChangedEventArgs e)
{
FolderView FolderView = (FolderView)Object;
FolderView.Refresh();
FolderView.SearchTextBox.Text = string.Empty;
}
#endregion
#region Methods
public virtual void GetItems(string Path, out List<string> Folders, out List<string> Files)
{
Folders = default(List<string>);
Files = default(List<string>);
}
/// <summary>
/// Refreshes current path with contents.
/// </summary>
public virtual void Refresh()
{
//Used to debug property values at runtime. So far the values for each object instance are unique.
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(this))
{
string name = descriptor.Name;
object value = descriptor.GetValue(this);
Console.WriteLine("{0}={1}", name, value);
}
}
/// <summary>
/// Populates controls with actual items via binding. We must do this on UI thread. This occurs immediately after <Refresh()>.
/// </summary>
/// <param name="Folders"></param>
/// <param name="Files"></param>
public virtual void Populate(List<FtpListItem> Folders, List<FtpListItem> Files)
{
}
public virtual void Populate(List<string> Folders, List<string> Files)
{
}
#endregion
#region FolderView
public FolderView()
{
InitializeComponent();
}
#endregion
}
LocalFolderView.cs (RemoteFolderView.cs aynı izler):
public sealed class LocalFolderView : FolderView
{
public override void GetItems(string Path, out List<string> Folders, out List<string> Files)
{
//These are my own functions
Folders = Directory.GetDirectories(Path);
Files = Directory.GetFiles(Path, null);
}
public override void Populate(List<string> Folders, List<string> Files)
{
int NumFolders = Folders.Count, NumFiles = Files.Count;
this.IsEmpty = NumFolders == 0 && NumFiles == 0 ? true : false;
if (Folders == null || Files == null || (NumFolders == 0 && NumFiles == 0)) return;
for (int j = 0, Count = NumFolders; j < Count; j++)
{
this.Items.Add(new BindableFolder(Folders[j]));
}
for (int j = 0, Count = NumFiles; j < Count; j++)
{
this.Items.Add(new BindableFile(Files[j]));
}
}
public override void Refresh()
{
base.Refresh();
this.Items.Clear();
//If directory doesn't exist, we don't want to enter it.
if (!System.IO.Directory.Exists(this.Path)) return;
List<string> Folders = null;
List<string> Files = null;
string CurrentPath = this.Path;
BackgroundWorker Worker = new BackgroundWorker();
Worker.DoWork += (s, e) =>
{
this.GetItems(CurrentPath, out Folders, out Files);
};
Worker.RunWorkerCompleted += (s, e) =>
{
//Start populating items
var DispatcherOperation = Application.Current.Dispatcher.BeginInvoke(new Action(() => this.Populate(Folders, Files)));
};
Worker.RunWorkerAsync();
}
}
not
Yapılacak :
- Her iki örnekte de FolderViews içindeki DataGrids aynı öğelerle doldurulur.
- Her bir FolderView örneğinin path özelliği farklıdır.
- Bu, yalnızca ikinci örneği öğelerle doldurduktan sonra ilkini yerleştirmeyi denedikten sonra gerçekleşir. İlk örneği ilk önce doldurursam, ikinci hiç bir şey olmaz.
- İki örneğin aynı öğelerle doldurulduğunu söylediğimde, ilkini doldurursam ilk öğenin ikinci sırada görüneceğini kastediyorum. Ve ikinciyi doldurursam, ikincisinin eşyaları ilk sırada görünür.
- Ayrıca, "populate" dediğimde,
Path
özelliğini FolderView olarak ayarlıyorum.
şeyler denedim:
- ben bağlamak şekilde değiştirilmesi. Örneğin,
Binding ElementName=explorer, Path=Property
gibi ciltleme yerine, onuBinding Property, RelativeSource={RelativeSource AncestorType={x:Type local:UserControlType}}
olarak değiştirirdim. - Çeşitli elemanlardan
x:Name
özelliklerini kaldırma. - Damping FolderView özellikleri/değerleri. Yukarıdaki kaynakta bir örnek.
Dürüst olmak gerekirse, nasıl hata ayıklama yapacağımı bilmiyorum. Bu bir hata mı yoksa bağlayıcı mantığım çok mantıklı değil mi?
Düzenleme
İşteİki Explorer örneklerini göstermek edebilirsiniz:
<local:LocalExplorer />
<local:RemoteExplorer/>
onlar ben de yanlışlıkla özellikle nasıl derinden dikkate başka bağlamak nasıl görmüyorum, hem kendi örnekleridir Verilen yuvalanmış ListBoxes görsel ağaçta.
Omg, TEŞEKKÜR EDERİZ. –