优化更新代码,添加界面功能并整合
This commit is contained in:
17
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyLibraryCmd.cs
Normal file
17
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyLibraryCmd.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows;
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.UI;
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary;
|
||||
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class FamilyLibraryCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
WinDialogHelper.ShowModeless<FamilyLibraryView>(new FamilyLibraryViewModel());
|
||||
}
|
||||
}
|
||||
315
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyLibraryView.xaml
Normal file
315
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyLibraryView.xaml
Normal file
@@ -0,0 +1,315 @@
|
||||
<ui:FluentWindowEx
|
||||
x:Class="ShrlAlgo.RvKits.RvFamily.FamilyLibrary.FamilyLibraryView"
|
||||
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:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:local="clr-namespace:ShrlAlgo.RvKits.RvFamily.FamilyLibrary"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="https://github.com/ShrlAlgo/WPFluent"
|
||||
Title="本地族库"
|
||||
Width="1050"
|
||||
Height="600"
|
||||
MinWidth="1050"
|
||||
MinHeight="600"
|
||||
d:DataContext="{d:DesignInstance Type=local:FamilyLibraryViewModel}"
|
||||
ResizeMode="CanResizeWithGrip"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/ShrlAlgo.RvKits;component/WPFUI.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="200" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="220" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ui:Button
|
||||
Grid.Row="0"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding SelectPathCommand}"
|
||||
Content="打开族目录"
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontFamily={StaticResource BoxIcons}}"
|
||||
ToolTip="{Binding FamilyPath, Mode=OneWay, StringFormat=族目录:{}{0}}" />
|
||||
<TreeView
|
||||
x:Name="FolderTreeView"
|
||||
Grid.Row="1"
|
||||
d:ItemsSource="{d:SampleData}"
|
||||
ItemsSource="{Binding FolderTreeViewItems}">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectedItemChanged">
|
||||
<i:InvokeCommandAction Command="{Binding SelectDirTreeNodeCommand}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type TreeView}, Mode=FindAncestor}}" />
|
||||
<!--<behaviors:InvokeCommandAction Command="{Binding SetSelectedItem}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TreeView}}" />-->
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TreeView>
|
||||
<GridSplitter
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="1"
|
||||
HorizontalAlignment="Center"
|
||||
ShowsPreview="True" />
|
||||
<ui:TextBox
|
||||
x:Name="SearchBox"
|
||||
Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
Margin="5"
|
||||
Cursor="IBeam"
|
||||
PlaceholderText="请输入搜索关键词">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="KeyDown">
|
||||
<i:InvokeCommandAction Command="{Binding SearchFamilyCommand}" CommandParameter="{Binding Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}, Mode=FindAncestor}}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ui:TextBox>
|
||||
<ui:ListView
|
||||
Grid.Row="1"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="2"
|
||||
d:ItemsSource="{d:SampleData}"
|
||||
ItemsSource="{Binding FamilyPageListViewItems}"
|
||||
SelectedItem="{Binding SelectedFamily}">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<i:InvokeCommandAction Command="{Binding LvSelectionChangedCommand}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type ListView}, Mode=FindAncestor}}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<!--<ListView.View>
|
||||
<GridView>
|
||||
<GridViewColumn Header="缩略图" >
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<Image Source="{Binding ImageData}"/>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
<GridViewColumn DisplayMemberBinding="{Binding Title}" Header="名称" />
|
||||
<GridViewColumn DisplayMemberBinding="{Binding Path}" Header="路径" />
|
||||
<GridViewColumn DisplayMemberBinding="{Binding RevitVersion}" Header="版本" />
|
||||
<GridViewColumn>
|
||||
<GridViewColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button
|
||||
Command="{Binding DataContext.ImportFamilyCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="载入"
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="将族载入到当前项目" />
|
||||
<Button
|
||||
Command="{Binding DataContext.LocationFamilyFileCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="浏览"
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="在资源管理器中浏览文件" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</GridViewColumn.CellTemplate>
|
||||
</GridViewColumn>
|
||||
</GridView>
|
||||
</ListView.View>-->
|
||||
<ui:ListView.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ListViewItem}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ListViewItem}">
|
||||
<Border
|
||||
x:Name="border"
|
||||
Margin="5"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="2"
|
||||
CornerRadius="5">
|
||||
<ContentPresenter />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsMouseOver" Value="True" />
|
||||
<Condition Property="IsSelected" Value="False" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="border" Property="BorderBrush" Value="Gray" />
|
||||
</MultiTrigger>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="border" Property="BorderBrush" Value="LightSkyBlue" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ui:ListView.ItemContainerStyle>
|
||||
<ui:ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType={x:Type ScrollContentPresenter}}}" />
|
||||
</ItemsPanelTemplate>
|
||||
</ui:ListView.ItemsPanel>
|
||||
<ui:ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ui:Card Padding="0">
|
||||
<Grid Width="170" Height="210">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="170" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
Grid.Row="0"
|
||||
Width="128"
|
||||
Height="128"
|
||||
Source="{Binding ImageData}"
|
||||
Stretch="Uniform"
|
||||
ToolTip="{Binding ToolTip}" />
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom"
|
||||
Orientation="Horizontal">
|
||||
<StackPanel.Style>
|
||||
<Style TargetType="{x:Type StackPanel}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}, Mode=FindAncestor}}" Value="True">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<ui:Button
|
||||
Appearance="Primary"
|
||||
Command="{Binding DataContext.ImportFamilyCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="载入"
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="将族载入到当前项目" />
|
||||
<ui:Button
|
||||
Appearance="Primary"
|
||||
Command="{Binding DataContext.LocationFamilyFileCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content="定位"
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="在资源管理器中浏览文件" />
|
||||
<!--
|
||||
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}"
|
||||
CommandParameter="{Binding DataContext, RelativeSource={RelativeSource Mode=Self}}" 等价于 CommandParameter="{Binding}"
|
||||
-->
|
||||
</StackPanel>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Width="128"
|
||||
Text="{Binding Title}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="WrapWithOverflow" />
|
||||
</Grid>
|
||||
</ui:Card>
|
||||
</DataTemplate>
|
||||
</ui:ListView.ItemTemplate>
|
||||
<ui:ListView.Template>
|
||||
<ControlTemplate TargetType="{x:Type ListView}">
|
||||
<ScrollViewer
|
||||
x:Name="scr"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="ScrollChanged">
|
||||
<i:InvokeCommandAction Command="{Binding LvScrollCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ScrollViewer}, Mode=FindAncestor}}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<WrapPanel IsItemsHost="True" ScrollViewer.CanContentScroll="True" />
|
||||
</ScrollViewer>
|
||||
</ControlTemplate>
|
||||
</ui:ListView.Template>
|
||||
</ui:ListView>
|
||||
<GridSplitter
|
||||
Grid.Row="1"
|
||||
Grid.Column="3"
|
||||
Width="1"
|
||||
HorizontalAlignment="Center"
|
||||
ShowsPreview="True" />
|
||||
<ui:DataGrid
|
||||
Grid.Row="1"
|
||||
Grid.Column="4"
|
||||
Margin="5"
|
||||
d:ItemsSource="{d:SampleData}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding SelectedItem.Parameters, ElementName=CbbSymbols, Mode=TwoWay}">
|
||||
<ui:DataGrid.Columns>
|
||||
<DataGridTextColumn Binding="{Binding Name}" Header="属性名" />
|
||||
<DataGridTextColumn Binding="{Binding Value}" Header="属性值" />
|
||||
</ui:DataGrid.Columns>
|
||||
</ui:DataGrid>
|
||||
<!--<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="2"
|
||||
Margin="5"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top">
|
||||
<hc:ButtonGroup Style="{StaticResource ButtonGroupSolid}">
|
||||
<RadioButton IsChecked="True" Style="{StaticResource RadioGroupItemHorizontalFirst}">
|
||||
<hc:Interaction.Triggers>
|
||||
<hc:EventTrigger EventName="Checked">
|
||||
<hc:EventToCommand Command="{Binding ModifyLayout}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}" />
|
||||
</hc:EventTrigger>
|
||||
</hc:Interaction.Triggers>
|
||||
</RadioButton>
|
||||
<RadioButton Style="{StaticResource RadioGroupItemHorizontalLast}">
|
||||
<hc:Interaction.Triggers>
|
||||
<hc:EventTrigger EventName="Checked">
|
||||
<hc:EventToCommand Command="{Binding ModifyLayout}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=RadioButton}}" />
|
||||
</hc:EventTrigger>
|
||||
</hc:Interaction.Triggers>
|
||||
</RadioButton>
|
||||
</hc:ButtonGroup>
|
||||
</StackPanel>-->
|
||||
<ui:StackPanelEx
|
||||
Grid.Row="0"
|
||||
Grid.Column="4"
|
||||
Orientation="Horizontal">
|
||||
<ui:ComboBoxEx
|
||||
x:Name="CbbSymbols"
|
||||
ui:StackPanelEx.Fill="Fill"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding SymbolTypes, Mode=TwoWay}"
|
||||
PlaceholderText="选择族类型"
|
||||
SelectedItem="{Binding SelectedSymbolType, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Margin="5"
|
||||
ui:StackPanelEx.Fill="Auto"
|
||||
Command="{Binding ImportFamilySymbolCommand}"
|
||||
Content=""
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="载入类型" />
|
||||
</ui:StackPanelEx>
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="5"
|
||||
Text="{Binding FamilyCount, Mode=OneWay, StringFormat=共计{}{0}个}" />
|
||||
<ui:InfoBar
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
IsOpen="{Binding ActiveSnackbar}"
|
||||
Message="{Binding Message}" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="4"
|
||||
Text="{Binding RevitVersion, Mode=OneWay, StringFormat=当前文件版本:Revit \{0\}}" />
|
||||
</Grid>
|
||||
</ui:FluentWindowEx>
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// LocalFamily.xaml 的交互逻辑.
|
||||
/// </summary>
|
||||
public partial class FamilyLibraryView
|
||||
{
|
||||
public FamilyLibraryView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
483
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyLibraryViewModel.cs
Normal file
483
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyLibraryViewModel.cs
Normal file
@@ -0,0 +1,483 @@
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using FuzzySharp;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
using System.IO;
|
||||
|
||||
using System.Windows;
|
||||
|
||||
using System.Windows.Controls;
|
||||
|
||||
|
||||
using Settings = ShrlAlgo.RvKits.Properties.Settings;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary;
|
||||
|
||||
public partial class FamilyLibraryViewModel : ObservableObject
|
||||
{
|
||||
public FamilyLibraryViewModel()
|
||||
{
|
||||
loadFamilyHandler = new ActionEventHandler();
|
||||
loadFamilySymbolHandler = new ActionEventHandler();
|
||||
#if REVIT2018
|
||||
familyPath = Settings.Default.FamilyPath_2018;
|
||||
#elif REVIT2019
|
||||
familyPath = Settings.Default.FamilyPath_2019;
|
||||
#elif REVIT2020
|
||||
familyPath = Settings.Default.FamilyPath_2020;
|
||||
#elif REVIT2021
|
||||
familyPath = Settings.Default.FamilyPath_2021;
|
||||
#endif
|
||||
PageSize = 20;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private readonly ActionEventHandler loadFamilyHandler;
|
||||
private readonly ActionEventHandler loadFamilySymbolHandler;
|
||||
|
||||
[ObservableProperty]
|
||||
private string familyPath;
|
||||
|
||||
[ObservableProperty]
|
||||
private int pageCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private int pageSize;
|
||||
|
||||
[ObservableProperty]
|
||||
private string revitVersion;
|
||||
|
||||
[ObservableProperty]
|
||||
private FamilyModel selectedFamily;
|
||||
|
||||
[ObservableProperty]
|
||||
private FamilySymbolType selectedSymbolType;
|
||||
|
||||
[ObservableProperty]
|
||||
private List<FamilySymbolType> symbolTypes;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool activeSnackbar;
|
||||
|
||||
[ObservableProperty]
|
||||
private WPFluent.Controls.InfoBar messageQueue = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private string message;
|
||||
|
||||
partial void OnMessageChanged(string value)
|
||||
{
|
||||
ActiveSnackbar = true;
|
||||
}
|
||||
|
||||
public int FamilyCount => FamilyDataSource.Count;
|
||||
|
||||
/// <summary>
|
||||
/// 选择树路径时的源
|
||||
/// </summary>
|
||||
public ObservableCollection<FamilyModel> FamilyDataSource { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 单页显示的源
|
||||
/// </summary>
|
||||
public ObservableCollection<FamilyModel> FamilyPageListViewItems { get; set; } = new();
|
||||
|
||||
public ObservableCollection<TreeViewItem> FolderTreeViewItems { get; set; } = new();
|
||||
|
||||
[RelayCommand]
|
||||
private void LvScroll(ScrollViewer scrollViewer)
|
||||
{
|
||||
// ReSharper disable once CompareOfFloatsByEqualityOperator
|
||||
if (!isLoadingData && scrollViewer.VerticalOffset + scrollViewer.ViewportHeight == scrollViewer.ExtentHeight)
|
||||
{
|
||||
LoadMoreData();
|
||||
}
|
||||
}
|
||||
|
||||
private const int BatchSize = 10;
|
||||
private bool isLoadingData;
|
||||
|
||||
/// <summary>
|
||||
/// 加载目录树节点的初始化数据
|
||||
/// </summary>
|
||||
private void LoadInitialData()
|
||||
{
|
||||
isLoadingData = true;
|
||||
FamilyPageListViewItems.Clear();
|
||||
var size = BatchSize;
|
||||
if (FamilyDataSource.Count < BatchSize)
|
||||
{
|
||||
size = FamilyDataSource.Count;
|
||||
}
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
FamilyPageListViewItems.Add(FamilyDataSource[i]);
|
||||
}
|
||||
isLoadingData = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 懒加载
|
||||
/// </summary>
|
||||
private void LoadMoreData()
|
||||
{
|
||||
isLoadingData = true;
|
||||
var startIndex = FamilyPageListViewItems.Count;
|
||||
var end = startIndex + BatchSize;
|
||||
if (end > FamilyDataSource.Count)
|
||||
{
|
||||
end = FamilyDataSource.Count;
|
||||
}
|
||||
if (startIndex < end + 1)
|
||||
{
|
||||
for (var i = startIndex; i < end; i++)
|
||||
{
|
||||
FamilyPageListViewItems.Add(FamilyDataSource[i]);
|
||||
}
|
||||
}
|
||||
isLoadingData = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归获取路径下的所有族文件
|
||||
/// </summary>
|
||||
/// <param name="fullPath"></param>
|
||||
private void GetFamilyFile(string fullPath)
|
||||
{
|
||||
DirectoryInfo dir = new(fullPath);
|
||||
try
|
||||
{
|
||||
if (!dir.Exists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//文件系统,包含文件夹和文件
|
||||
var files = dir.GetFileSystemInfos();
|
||||
foreach (var fSys in files)
|
||||
{
|
||||
//FSys如果是文件则fileinfo不为空
|
||||
|
||||
if (fSys is FileInfo fileInfo)
|
||||
{
|
||||
if (fileInfo.Extension == ".rfa")
|
||||
{
|
||||
var sfInfo = new FileInfo(fileInfo.DirectoryName + "\\" + fileInfo.Name);
|
||||
//RevitFileUtil.ParserRevitFile(sfInfo.FullName);
|
||||
var model = new FamilyModel
|
||||
{
|
||||
FileInfo = sfInfo,
|
||||
Path = sfInfo.FullName,
|
||||
Title = Path.GetFileNameWithoutExtension(sfInfo.FullName),
|
||||
ToolTip = sfInfo.Name
|
||||
//RevitVersion = RevitFileUtil.RevitVersion
|
||||
};
|
||||
|
||||
FamilyDataSource.Add(model);
|
||||
}
|
||||
}
|
||||
else //当fileinfo为空,即为文件夹,向下查找
|
||||
{
|
||||
GetFamilyFile($"{fullPath}\\{fSys}");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将族加载到当前文件中
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void ImportFamily(FamilyModel model)
|
||||
{
|
||||
//将model的绑定数据传给外部事件
|
||||
loadFamilyHandler.Raise(app =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = app.ActiveUIDocument.Document;
|
||||
Family family;
|
||||
FamilySymbol fs = null;
|
||||
doc.Invoke(
|
||||
_ =>
|
||||
{
|
||||
family = doc.GetOrLoadedFamily(model.Path);
|
||||
fs = doc.GetElement(family.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
|
||||
//if (fs != null && !fs.IsActive)
|
||||
//{
|
||||
// fs.Activate();
|
||||
//}
|
||||
//if (family == null)
|
||||
//{
|
||||
// doc.LoadFamily(FileLibModel.Path, familyLoadOption, out family);
|
||||
// fs = doc.GetElement(family.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
|
||||
//
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// MessageBox.ShowAhead("族已载入或载入失败。", "提示");
|
||||
//}
|
||||
},
|
||||
"载入族-" + Path.GetFileNameWithoutExtension(model.Path)
|
||||
);
|
||||
if (fs != null && app.ActiveUIDocument.CanPlaceElementType(fs))
|
||||
{
|
||||
app.ActiveUIDocument.PromptForFamilyInstancePlacement(fs);
|
||||
}
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
Message = e.Message;
|
||||
e.Message.ToLog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void ImportFamilySymbol()
|
||||
{
|
||||
if (SelectedFamily == null || SelectedSymbolType == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
loadFamilySymbolHandler.Raise(app =>
|
||||
{
|
||||
var uidoc = app.ActiveUIDocument;
|
||||
var doc = uidoc.Document;
|
||||
//当前选择的族类型
|
||||
FamilySymbol fs = null;
|
||||
if (SelectedSymbolType.Name == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
doc.Invoke(
|
||||
_ =>
|
||||
{
|
||||
var fam = doc.GetOrLoadedFamily(SelectedFamily.Path);
|
||||
doc.Regenerate();
|
||||
//if (fam == null)
|
||||
//{
|
||||
// doc.LoadFamilySymbol(FamilyPath, FamilySymbolName, out fs);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
var x = fam.GetFamilySymbolIds()
|
||||
.FirstOrDefault(id => doc.GetElement(id).Name == SelectedSymbolType.Name);
|
||||
fs = doc.GetElement(x) as FamilySymbol;
|
||||
//}
|
||||
if (fs?.IsActive == false)
|
||||
{
|
||||
fs.Activate();
|
||||
}
|
||||
},
|
||||
"载入族-" + Path.GetFileNameWithoutExtension(SelectedFamily.Path) + " 类型:" + SelectedSymbolType.Name
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
if (fs != null && uidoc.CanPlaceElementType(fs))
|
||||
{
|
||||
app.ActiveUIDocument.PromptForFamilyInstancePlacement(fs);
|
||||
}
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Message.ToLog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
PopulateTreeView(FamilyPath);
|
||||
GetFamilyFile(FamilyPath);
|
||||
//CurrentPageIndex = 0;
|
||||
LoadInitialData();
|
||||
//PageCount = GetPageCount();
|
||||
//PageOrderNumberCollection = GetOrderIntCollection();
|
||||
//CollectionViewSource.GetDefaultView(FamilyPageListViewItems);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private static void LocationFamilyFile(object obj)
|
||||
{
|
||||
//System.Windows.Controls.Button btn = obj as System.Windows.Controls.Button;
|
||||
if (obj is FamilyModel familyInfo)
|
||||
{
|
||||
var proc = new System.Diagnostics.Process();
|
||||
proc.StartInfo.FileName = "explorer";
|
||||
//打开资源管理器
|
||||
proc.StartInfo.Arguments = "/select," + familyInfo.Path;
|
||||
proc.Start();
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void LvSelectionChanged(object obj)
|
||||
{
|
||||
if (obj is FamilyModel familyInfo)
|
||||
{
|
||||
RevitFileUtil.ParserRevitFile(familyInfo.Path);
|
||||
SymbolTypes = RevitFileUtil.SymbolTypes;
|
||||
SelectedSymbolType = SymbolTypes.FirstOrDefault();
|
||||
RevitVersion = RevitFileUtil.RevitVersion;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绑定TreeView数据源.
|
||||
/// </summary>
|
||||
/// <param name="path">The Path<see cref="string" />.</param>
|
||||
private void PopulateTreeView(string path)
|
||||
{
|
||||
FolderTreeViewItems?.Clear();
|
||||
|
||||
var info = new DirectoryInfo(path);
|
||||
if (!info.Exists)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rootNode = new TreeViewItem { Header = info.Name, Tag = info.FullName };
|
||||
|
||||
/* 项目“ShrlAlgo.RvKits (net481)”的未合并的更改
|
||||
在此之前:
|
||||
SubDirectories(info.GetDirectories(), rootNode);
|
||||
在此之后:
|
||||
FamilyLibraryViewModel.SubDirectories(info.GetDirectories(), rootNode);
|
||||
*/
|
||||
SubDirectories(info.GetDirectories(), rootNode);
|
||||
//dirTree.DataContext = rootNode;
|
||||
FolderTreeViewItems!.Add(rootNode);
|
||||
rootNode.IsExpanded = true;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SearchFamily(object obj)
|
||||
{
|
||||
//ListViewItem foundItem =
|
||||
// textListView.FindItemWithText(searchBox.Text, false, 0, true);
|
||||
//if (foundItem != null)
|
||||
//{
|
||||
// textListView.TopItem = foundItem;
|
||||
//}
|
||||
//Func<string, bool> searchFunc = BreakCurve;
|
||||
//Task<bool> task = new Task<bool>(() => BreakCurve(obj.ToString()));
|
||||
//task.Start();
|
||||
//await task;
|
||||
if (string.IsNullOrEmpty(obj.ToString()))
|
||||
{
|
||||
LoadInitialData();
|
||||
//FamilyPageListViewItems.Clear();
|
||||
//itemsLoaded.ForEach(item => FamilyPageListViewItems.Add(item));
|
||||
}
|
||||
else
|
||||
{
|
||||
//itemsLoaded.Clear();
|
||||
//FamilyPageListViewItems.ForEach(item => itemsLoaded.Add(item));
|
||||
FamilyPageListViewItems.Clear();
|
||||
foreach (var item in FamilyDataSource)
|
||||
{
|
||||
if (Fuzz.PartialRatio(item.Title, obj.ToString()) > 70)
|
||||
{
|
||||
FamilyPageListViewItems.Add(item);
|
||||
|
||||
}
|
||||
//if (item.Title.Contains(obj.ToString()))
|
||||
//{
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选择树状节点
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
[RelayCommand]
|
||||
private void SelectDirTreeNode(object obj)
|
||||
{
|
||||
//e.OriginalSource 就是TreeViewItem对象,你可以将其保存到窗体类的某个私有字段中,或者直接使用它,如下所示:
|
||||
FamilyDataSource.Clear();
|
||||
if (obj is TreeViewItem selectedItem)
|
||||
{
|
||||
GetFamilyFile(selectedItem.Tag.ToString());
|
||||
}
|
||||
LoadInitialData();
|
||||
SymbolTypes = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 路径选择.
|
||||
/// </summary>
|
||||
[RelayCommand]
|
||||
private void SelectPath()
|
||||
{
|
||||
var dialog = new WPFluent.Controls.VistaFolderBrowserDialog();
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if REVIT2018
|
||||
Settings.Default.FamilyPath_2018 = dialog.SelectedPath;
|
||||
#elif REVIT2019
|
||||
Settings.Default.FamilyPath_2019 = dialog.SelectedPath;
|
||||
#elif REVIT2020
|
||||
Settings.Default.FamilyPath_2020 = dialog.SelectedPath;
|
||||
#elif REVIT2021
|
||||
Settings.Default.FamilyPath_2021 = dialog.SelectedPath;
|
||||
#endif
|
||||
PopulateTreeView(dialog.SelectedPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归添加目录结构到TreeView根节点.
|
||||
/// </summary>
|
||||
/// <param name="subDirs">.</param>
|
||||
/// <param name="nodeToAddTo">根节点.</param>
|
||||
private static void SubDirectories(DirectoryInfo[] subDirs, TreeViewItem nodeToAddTo)
|
||||
{
|
||||
//父节点
|
||||
foreach (var subDir in subDirs)
|
||||
{
|
||||
var aNode = new TreeViewItem { Header = subDir.Name, Tag = subDir.FullName };
|
||||
//获取子目录
|
||||
var subSubDirs = subDir.GetDirectories();
|
||||
if (subSubDirs.Length != 0)
|
||||
{
|
||||
/* 项目“ShrlAlgo.RvKits (net481)”的未合并的更改
|
||||
在此之前:
|
||||
SubDirectories(subSubDirs, aNode);
|
||||
在此之后:
|
||||
FamilyLibraryViewModel.SubDirectories(subSubDirs, aNode);
|
||||
*/
|
||||
SubDirectories(subSubDirs, aNode);
|
||||
}
|
||||
|
||||
nodeToAddTo.Items.Add(aNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
93
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyModel.cs
Normal file
93
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/FamilyModel.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using ShrlAlgo.Toolkit.Core.Extensions;
|
||||
|
||||
using System.IO;
|
||||
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary;
|
||||
|
||||
public partial class FamilyModel : ObservableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 族库缩略图
|
||||
/// </summary>
|
||||
public BitmapSource ImageData => ImageExtensions.LoadFileImage(Path, 128, 128);
|
||||
|
||||
/// <summary>
|
||||
/// 最近使用面板
|
||||
/// </summary>
|
||||
public BitmapImage BitmapImage { get; set; }
|
||||
|
||||
public FileInfo FileInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 族库文件标题
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
|
||||
public Family ReferenceFamily { get; set; }
|
||||
public string ToolTip { get; set; }
|
||||
public UIApplication UiApplication { get; set; }
|
||||
public string Path { get; set; }
|
||||
public string RevitVersion { get; set; }
|
||||
public ElementId FamilyId => ReferenceFamily.Id;
|
||||
|
||||
//private bool CanPlace()
|
||||
//{
|
||||
// uiApplication.ActiveUIDocument.Document.is
|
||||
// return ReferenceFamily.IsValidObject;
|
||||
// .IsValidObject = true;
|
||||
//}
|
||||
|
||||
[RelayCommand]
|
||||
private static void PlaceRecentFamily(object obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (obj is FamilyModel { ReferenceFamily: { } family } info)
|
||||
{
|
||||
var uidoc = info.UiApplication.ActiveUIDocument;
|
||||
var doc = uidoc.Document;
|
||||
|
||||
if (family.IsValidObject && doc.PathName == family.Document.PathName)
|
||||
{
|
||||
var fs = doc.GetElement(family.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
|
||||
uidoc.PostRequestForElementTypePlacement(fs);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// var docs = info.uiApplication.Application.Documents;
|
||||
// foreach (Document d in docs)
|
||||
// {
|
||||
// if (d.PathName == family.Document.PathName)
|
||||
// {
|
||||
// List<ElementId> list = new List<ElementId>()
|
||||
// {
|
||||
// family.ViewId
|
||||
// };
|
||||
// doc.Invoke(ts =>
|
||||
// {
|
||||
// ElementTransformUtils.CopyElements(d, list, doc, null, new CopyPasteOptions());
|
||||
// },"复制族");
|
||||
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
}
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
e.ToLog();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary
|
||||
{
|
||||
public class LoadedFamilyDropHandler : IDropHandler
|
||||
{
|
||||
public void Execute(UIDocument document, object data)
|
||||
{
|
||||
ElementId familySymbolId = (ElementId)data;
|
||||
if (document.Document.GetElement(familySymbolId) is FamilySymbol symbol)
|
||||
{
|
||||
document.PromptForFamilyInstancePlacement(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/Models.cs
Normal file
16
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/Models.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary
|
||||
{
|
||||
public class FamilySymbolType
|
||||
{
|
||||
public List<Parameter> Parameters { get; set; } = new();
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
public class Parameter
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Value { get; set; }
|
||||
public string TypeOfParameter { get; set; }
|
||||
}
|
||||
}
|
||||
644
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/RevitFileUtil.cs
Normal file
644
ShrlAlgo.RvKits/RvFamily/FamilyLibrary/RevitFileUtil.cs
Normal file
@@ -0,0 +1,644 @@
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Xml;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily.FamilyLibrary
|
||||
{
|
||||
/// <summary>
|
||||
/// 直接读取文件的信息(不依赖RevitAPI)
|
||||
/// </summary>
|
||||
internal static class RevitFileUtil
|
||||
{
|
||||
private static string _fileName;
|
||||
|
||||
public static Image PreviewImage { get; set; }
|
||||
public static List<FamilySymbolType> SymbolTypes { get; set; }
|
||||
|
||||
public static StringBuilder FileInfo { get; set; }
|
||||
public static StringBuilder Content { get; set; }
|
||||
public static StringBuilder TransMissionData { get; set; }
|
||||
public static string SafeName { get; set; }
|
||||
public static string Product { get; set; }
|
||||
public static string RevitVersion { get; set; }
|
||||
public static string UpdateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图片资源转字节
|
||||
/// </summary>
|
||||
/// <param name="bitmapSource"></param>
|
||||
/// <returns></returns>
|
||||
public static byte[] BitSourceToArray(BitmapSource bitmapSource)
|
||||
{
|
||||
BitmapEncoder encoder = new JpegBitmapEncoder();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
|
||||
encoder.Save(ms);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static StringBuilder GetFamilyInfo(List<FamilySymbolType> symbols)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (FamilySymbolType symbol in symbols)
|
||||
{
|
||||
sb.Append($"族类型:{symbol.Name}{symbol.Value}\r\n");
|
||||
foreach (Parameter param in symbol.Parameters)
|
||||
{
|
||||
sb.Append($" {param.Name}:{param.Value}\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static int GetPngStartingOffset(byte[] previewData)
|
||||
{
|
||||
bool markerFound = false;
|
||||
int startingOffset = 0;
|
||||
int previousValue = 0;
|
||||
using (MemoryStream ms = new MemoryStream(previewData))
|
||||
{
|
||||
for (int i = 0; i < previewData.Length; i++)
|
||||
{
|
||||
int currentValue = ms.ReadByte();
|
||||
// possible start of PNG file data
|
||||
if (currentValue == 137) // 0x89
|
||||
{
|
||||
markerFound = true;
|
||||
startingOffset = i;
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (currentValue)
|
||||
{
|
||||
case 80: // 0x50
|
||||
if (markerFound && previousValue == 137)
|
||||
{
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
break;
|
||||
|
||||
case 78: // 0x4E
|
||||
if (markerFound && previousValue == 80)
|
||||
{
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
break;
|
||||
|
||||
case 71: // 0x47
|
||||
if (markerFound && previousValue == 78)
|
||||
{
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
break;
|
||||
|
||||
case 13: // 0x0D
|
||||
if (markerFound && previousValue == 71)
|
||||
{
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
break;
|
||||
|
||||
case 10: // 0x0A
|
||||
if (markerFound && previousValue == 26)
|
||||
{
|
||||
return startingOffset;
|
||||
}
|
||||
|
||||
if (markerFound && previousValue == 13)
|
||||
{
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
break;
|
||||
|
||||
case 26: // 0x1A
|
||||
if (markerFound && previousValue == 10)
|
||||
{
|
||||
previousValue = currentValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
markerFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取缩略图
|
||||
/// </summary>
|
||||
/// <param name="previewData"></param>
|
||||
/// <returns></returns>
|
||||
public static Image GetPreviewAsImage(byte[] previewData)
|
||||
{
|
||||
if (previewData == null || previewData.Length <= 0)
|
||||
{
|
||||
using (Bitmap newBitmap = new Bitmap(128, 128))
|
||||
{
|
||||
return newBitmap.Clone() as Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
// read past the Revit metadata to the start of the PNG image
|
||||
int startingOffset = GetPngStartingOffset(previewData);
|
||||
if (startingOffset == 0)
|
||||
{
|
||||
using (Bitmap newBitmap = new Bitmap(128, 128))
|
||||
{
|
||||
return newBitmap.Clone() as Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
byte[] pngDataBuffer = new byte[previewData.GetUpperBound(0) - startingOffset + 1];
|
||||
// read the PNG image data into a byte array
|
||||
using (MemoryStream ms = new MemoryStream(previewData))
|
||||
{
|
||||
ms.Position = startingOffset;
|
||||
ms.Read(pngDataBuffer, 0, pngDataBuffer.Length);
|
||||
}
|
||||
|
||||
byte[] decoderData = null;
|
||||
|
||||
// if the image data is valid
|
||||
if (pngDataBuffer != null)
|
||||
{
|
||||
// use a memory stream to decode the PNG image data
|
||||
// and copy the decoded data into a byte array
|
||||
using (MemoryStream ms = new MemoryStream(pngDataBuffer))
|
||||
{
|
||||
PngBitmapDecoder decoder = new PngBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat,
|
||||
BitmapCacheOption.Default);
|
||||
decoderData = BitSourceToArray(decoder.Frames[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// if the decoded data is valie
|
||||
if (decoderData != null && decoderData.Length > 0)
|
||||
{
|
||||
// use another memory stream to create a Bitmap
|
||||
// and then an Image from that Bitmap
|
||||
using (MemoryStream ms = new MemoryStream(decoderData))
|
||||
{
|
||||
using (Bitmap newBitmap = new Bitmap(ms))
|
||||
{
|
||||
using (Image newImage = newBitmap)
|
||||
{
|
||||
return newImage.Clone() as Image;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
using (Bitmap newBitmap = new Bitmap(128, 128))
|
||||
{
|
||||
return newBitmap.Clone() as Bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string ParseDetailInfo(string detailInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
detailInfo = detailInfo.Trim();
|
||||
int index = detailInfo.IndexOf(":");
|
||||
string detailValue = detailInfo.Substring(detailInfo.IndexOf(":") + 1);
|
||||
string detailKey = detailInfo.Substring(0, detailInfo.IndexOf(":"));
|
||||
detailKey = detailKey.Trim().ToUpper().Replace(" ", string.Empty);
|
||||
detailKey = PurgeUnprintableCharacters(detailKey);
|
||||
detailValue = PurgeUnprintableCharacters(detailValue);
|
||||
return $"{detailKey}:{detailValue}";
|
||||
//Console.WriteLine($"{detailKey}:{detailValue}");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return detailInfo;
|
||||
}
|
||||
|
||||
//switch (detailKey)
|
||||
//{
|
||||
// case "WORKSHARING":
|
||||
// if (string.IsNullOrEmpty(detailValue))
|
||||
// {
|
||||
// WorkSharing = WorkSharingMode.Unknown;
|
||||
// return;
|
||||
// }
|
||||
|
||||
// string workSharing = detailValue.Replace(" ", string.Empty).Trim().ToUpper();
|
||||
// switch (workSharing)
|
||||
// {
|
||||
// case "NOTENABLED":
|
||||
// WorkSharing = WorkSharingMode.NotEnabled;
|
||||
// break;
|
||||
|
||||
// case "LOCAL":
|
||||
// WorkSharing = WorkSharingMode.Local;
|
||||
// break;
|
||||
|
||||
// case "CENTRAL":
|
||||
// WorkSharing = WorkSharingMode.Central;
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// WorkSharing = WorkSharingMode.Unknown;
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case "USERNAME":
|
||||
// UserName = detailValue.Trim();
|
||||
// break;
|
||||
|
||||
// case "CENTRALFILEPATH":
|
||||
// CentralFilePath = detailValue.Trim();
|
||||
// break;
|
||||
|
||||
// case "REVITBUILD":
|
||||
// RevitBuild = detailValue.Trim();
|
||||
// break;
|
||||
|
||||
// case "LASTSAVEPATH":
|
||||
// LastSavedpath = detailValue.Trim();
|
||||
// break;
|
||||
|
||||
// case "OPENWORKSETDEFAULT":
|
||||
// OpenWorksetDefault = Convert.ToInt32(detailValue.Trim());
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// Console.WriteLine($"{detailKey}:{detailValue}");
|
||||
// //Debug.Assert(false, string.Format("{0} was not found in the case tests.", detailKey));
|
||||
// break;
|
||||
//}
|
||||
}
|
||||
|
||||
public static StringBuilder ParseFileInfo(string unicodeData)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
||||
string[] basicFileInfoParts = unicodeData.Split('\0');
|
||||
|
||||
foreach (string basicFileInfoPart in basicFileInfoParts)
|
||||
{
|
||||
if (basicFileInfoPart.IndexOf("\r\n", StringComparison.Ordinal) >= 0)
|
||||
{
|
||||
string[] detailInfoParts = basicFileInfoPart.Split(new[] { "\r\n" }, new StringSplitOptions());
|
||||
foreach (string detailPart in detailInfoParts)
|
||||
{
|
||||
s.Append(ParseDetailInfo(detailPart) + "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析参数
|
||||
/// </summary>
|
||||
/// <param name="streamInfo"></param>
|
||||
public static List<FamilySymbolType> ParseParameter(StreamInfo streamInfo)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
|
||||
string xmlStr;
|
||||
byte[] streamData;
|
||||
using (Stream streamReader = streamInfo.GetStream(FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
streamData = new byte[streamReader.Length];
|
||||
streamReader.Read(streamData, 0, streamData.Length);
|
||||
xmlStr = Encoding.UTF8.GetString(streamData);
|
||||
document.LoadXml(xmlStr);
|
||||
//string xmldocpath = Path.GetFileNameWithoutExtension(FileName) + ".xml";
|
||||
//document.Save(xmldocpath);
|
||||
|
||||
//读取参数信息
|
||||
XmlElement root = document.DocumentElement;
|
||||
//节点前缀的命名空间
|
||||
string nameSpace = root.GetNamespaceOfPrefix("A");
|
||||
//string nameSpace = root.NamespaceURI;
|
||||
XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
|
||||
;
|
||||
nsmgr.AddNamespace("entry", nameSpace);
|
||||
|
||||
//族类型
|
||||
XmlNodeList xnlist = document.GetElementsByTagName("A:part");
|
||||
|
||||
XmlNodeList fileinfo = document.GetElementsByTagName("A:design-file");
|
||||
foreach (XmlNode xn in fileinfo)
|
||||
{
|
||||
if (xn.HasChildNodes)
|
||||
{
|
||||
foreach (XmlNode child in xn.ChildNodes)
|
||||
{
|
||||
if (child.Name == "A:title")
|
||||
{
|
||||
SafeName = child.InnerText;
|
||||
}
|
||||
|
||||
if (child.Name == "A:product")
|
||||
{
|
||||
Product = child.InnerText;
|
||||
}
|
||||
|
||||
if (child.Name == "A:product-version")
|
||||
{
|
||||
RevitVersion = child.InnerText;
|
||||
}
|
||||
|
||||
if (child.Name == "A:product-updated")
|
||||
{
|
||||
UpdateTime = child.InnerText;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//XmlNode rootnode = document.SelectSingleNode("/entry/A: family/A:part", nsmgr);
|
||||
//XmlNodeList xnlist = rootnode.ChildNodes;
|
||||
|
||||
List<FamilySymbolType> symbols = new List<FamilySymbolType>();
|
||||
foreach (XmlNode xn in xnlist)
|
||||
{
|
||||
//XmlAttributeCollection attriCol = xn.Attributes;
|
||||
//foreach (XmlAttribute xmlAttri in attriCol)
|
||||
//{
|
||||
// string name = xmlAttri.Name;
|
||||
// string value = xmlAttri.Value;
|
||||
|
||||
//}
|
||||
FamilySymbolType symbol = new FamilySymbolType();
|
||||
if (xn.HasChildNodes)
|
||||
{
|
||||
foreach (XmlNode child in xn.ChildNodes)
|
||||
{
|
||||
Parameter p = new Parameter();
|
||||
if (child.Name == "title")
|
||||
{
|
||||
symbol.Name = child.InnerText;
|
||||
continue;
|
||||
}
|
||||
|
||||
//族类型节点
|
||||
p.Name = child.Name;
|
||||
//族名称
|
||||
p.Value = child.InnerText;
|
||||
symbol.Parameters.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
symbols.Add(symbol);
|
||||
}
|
||||
|
||||
return symbols;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ParserRevitFile(string filename)
|
||||
{
|
||||
if (filename.EndsWith(".rvt") || filename.EndsWith(".rte") || filename.EndsWith(".rfa") ||
|
||||
filename.EndsWith(".rft"))
|
||||
{
|
||||
_fileName = filename;
|
||||
|
||||
//获取Storageroot Object
|
||||
BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public |
|
||||
BindingFlags.NonPublic | BindingFlags.InvokeMethod;
|
||||
|
||||
Type storageRootType = typeof(StorageInfo).Assembly.GetType("System.IO.Packaging.StorageRoot", true, false);
|
||||
//Type storageRootType = typeof(StorageInfo).Assembly.GetType("System.IO.Packaging", true, false);
|
||||
object[] file =
|
||||
{
|
||||
filename,
|
||||
FileMode.Open,
|
||||
FileAccess.Read,
|
||||
FileShare.Read
|
||||
};
|
||||
StorageInfo Storage = (StorageInfo)storageRootType.InvokeMember("Open", bindingFlags, null, null, file);
|
||||
|
||||
//if (Storage != null)
|
||||
//{
|
||||
// storageRootType.InvokeMember("CloseTrigger", bindingFlags, null, Storage, file);
|
||||
|
||||
// //Console.Write($"{filename}文件无法作为结构存储,并打开打开");
|
||||
//}
|
||||
|
||||
//var x = Storage.ThumbnailImage.GetPreviewAsImage();
|
||||
//读取结构化存储文件
|
||||
StreamInfo[] streams = Storage.GetStreams();
|
||||
foreach (StreamInfo streamInfo in streams)
|
||||
{
|
||||
string unicodeData;
|
||||
byte[] streamData = null;
|
||||
using (Stream streamReader = streamInfo.GetStream(FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
streamData = new byte[streamReader.Length];
|
||||
streamReader.Read(streamData, 0, streamData.Length);
|
||||
unicodeData = Encoding.Unicode.GetString(streamData);
|
||||
//unicodeData = Encoding.UTF8.GetString(streamData);
|
||||
}
|
||||
|
||||
if (streamInfo.Name.ToUpper().Equals("BASICFILEINFO"))
|
||||
{
|
||||
FileInfo = ParseFileInfo(unicodeData);
|
||||
}
|
||||
|
||||
if (streamInfo.Name.ToUpper().Equals("PARTATOM"))
|
||||
{
|
||||
//Console.WriteLine("部分原子:\r\n" + ParsePartAtom(unicodeData));
|
||||
if (filename.EndsWith(".rfa"))
|
||||
{
|
||||
SymbolTypes = ParseParameter(streamInfo);
|
||||
//Console.WriteLine("族参数:\r\n" + GetFamilyInfo(symbols));
|
||||
}
|
||||
}
|
||||
|
||||
if (streamInfo.Name.ToUpper().Equals("TRANSMISSIONDATA"))
|
||||
{
|
||||
TransMissionData = ParseTransMissionData(unicodeData);
|
||||
}
|
||||
|
||||
if (streamInfo.Name.ToUpper().Equals("REVITPREVIEW4.0"))
|
||||
{
|
||||
PreviewImage = ParsePreview(streamInfo);
|
||||
}
|
||||
|
||||
if (streamInfo.Name.ToUpper().Equals("CONTENTS"))
|
||||
{
|
||||
Content = ParseContents(unicodeData);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if (Storage != null)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// storageRootType.InvokeMember("CloseTrigger", bindingFlags, null, Storage, file);
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// MessageBox.ShowAhead(ex.ViewMessage);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
public static StringBuilder ParseTransMissionData(string unicodeData)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
||||
string[] basicFileInfoParts = unicodeData.Split('\0');
|
||||
|
||||
foreach (string basicFileInfoPart in basicFileInfoParts)
|
||||
{
|
||||
if (basicFileInfoPart.IndexOf("\r\n") >= 0)
|
||||
{
|
||||
string[] detailInfoParts = basicFileInfoPart.Split(new[] { "\r\n" }, new StringSplitOptions());
|
||||
foreach (string detailPart in detailInfoParts)
|
||||
{
|
||||
s.Append(ParseDetailInfo(detailPart) + "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public static void ParseXmlDocument(XmlDocument document)
|
||||
{
|
||||
XmlNode rootNode = document.SelectSingleNode("A");
|
||||
XmlNodeList xmlNodeList = rootNode?.ChildNodes;
|
||||
if (xmlNodeList == null) return;
|
||||
foreach (XmlNode xn in xmlNodeList)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
}
|
||||
|
||||
XmlAttributeCollection xnAttributes = xn.Attributes;
|
||||
if (xnAttributes != null)
|
||||
foreach (XmlAttribute attribute in xnAttributes)
|
||||
{
|
||||
string name = attribute.Name;
|
||||
string value = attribute.Value;
|
||||
}
|
||||
|
||||
if (xn.HasChildNodes)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理无效字符
|
||||
/// </summary>
|
||||
/// <param name="oldValue"></param>
|
||||
/// <returns></returns>
|
||||
public static string PurgeUnprintableCharacters(string oldValue)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char[] oldValueArray = oldValue.ToCharArray();
|
||||
foreach (char letter in oldValueArray)
|
||||
{
|
||||
int decimalValue = letter;
|
||||
if (decimalValue >= 32 && decimalValue <= 126)
|
||||
{
|
||||
sb.Append(letter);
|
||||
}
|
||||
}
|
||||
|
||||
oldValue = sb.ToString();
|
||||
sb.Length = 0;
|
||||
sb.Capacity = 0;
|
||||
sb = null;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
private static StringBuilder ParseContents(string unicodeData)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
||||
string[] basicFileInfoParts = unicodeData.Split('\0');
|
||||
|
||||
foreach (string basicFileInfoPart in basicFileInfoParts)
|
||||
{
|
||||
if (basicFileInfoPart.IndexOf("\r\n", StringComparison.Ordinal) >= 0)
|
||||
{
|
||||
string[] detailInfoParts = basicFileInfoPart.Split(new[] { "\r\n" }, new StringSplitOptions());
|
||||
foreach (string detailPart in detailInfoParts)
|
||||
{
|
||||
s.Append(ParseDetailInfo(detailPart) + "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static StringBuilder ParsePartAtom(string unicodeData)
|
||||
{
|
||||
StringBuilder s = new StringBuilder();
|
||||
string[] basicFileInfoParts = unicodeData.Split('\0');
|
||||
|
||||
foreach (string basicFileInfoPart in basicFileInfoParts)
|
||||
{
|
||||
if (basicFileInfoPart.IndexOf("\r\n", StringComparison.Ordinal) >= 0)
|
||||
{
|
||||
string[] detailInfoParts = basicFileInfoPart.Split(new[] { "\r\n" }, new StringSplitOptions());
|
||||
foreach (string detailPart in detailInfoParts)
|
||||
{
|
||||
s.Append(ParseDetailInfo(detailPart) + "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static Image ParsePreview(StreamInfo stream)
|
||||
{
|
||||
byte[] streamData = null;
|
||||
using (Stream streamReader = stream.GetStream(FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
streamData = new byte[streamReader.Length];
|
||||
streamReader.Read(streamData, 0, streamData.Length);
|
||||
//unicodeData = Encoding.Unicode.GetString(streamData);
|
||||
//unicodeData = Encoding.UTF8.GetString(streamData);
|
||||
}
|
||||
|
||||
return GetPreviewAsImage(streamData);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
ShrlAlgo.RvKits/RvFamily/FamilyProcessorCmd.cs
Normal file
19
ShrlAlgo.RvKits/RvFamily/FamilyProcessorCmd.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
using ShrlAlgo.Toolkit.Core.Heplers;
|
||||
|
||||
using System.Windows;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class FamilyProcessorCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
WinDialogHelper.ShowModeless<FamilyProcessorView>(new FamilyProcessorViewModel(UiApplication));
|
||||
}
|
||||
}
|
||||
172
ShrlAlgo.RvKits/RvFamily/FamilyProcessorView.xaml
Normal file
172
ShrlAlgo.RvKits/RvFamily/FamilyProcessorView.xaml
Normal file
@@ -0,0 +1,172 @@
|
||||
<ui:FluentWindowEx
|
||||
x:Class="ShrlAlgo.RvKits.RvFamily.FamilyProcessorView"
|
||||
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:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:local="clr-namespace:ShrlAlgo.RvKits.RvFamily"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="https://github.com/ShrlAlgo/WPFluent"
|
||||
Title="族复用"
|
||||
Width="380"
|
||||
Height="600"
|
||||
MinWidth="380"
|
||||
MinHeight="400"
|
||||
d:DataContext="{d:DesignInstance Type=local:FamilyProcessorViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary Source="pack://application:,,,/ShrlAlgo.RvKits;component/WPFUI.xaml" />
|
||||
</Window.Resources>
|
||||
<TabControl Margin="5,5,5,5">
|
||||
<TabItem Header="保存族">
|
||||
<ui:AutoGridEx
|
||||
ChildMargin="5"
|
||||
Columns="*,*"
|
||||
Rows="*,Auto,Auto,Auto">
|
||||
<DataGrid
|
||||
x:Name="FamilySaveDg"
|
||||
Grid.ColumnSpan="2"
|
||||
d:ItemsSource="{d:SampleData}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding FamilyCollection}"
|
||||
SelectionMode="Extended">
|
||||
<!--<ui:DataGrid.RowHeaderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Width="35">
|
||||
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ui:DataGrid.RowHeaderTemplate>-->
|
||||
<DataGrid.Columns>
|
||||
<DataGridCheckBoxColumn
|
||||
Width="60"
|
||||
Binding="{Binding IsSelected, Mode=OneWayToSource, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}"
|
||||
ElementStyle="{StaticResource DataGridCheckBoxElementDefaultStyle}"
|
||||
Header="选择" />
|
||||
<DataGridTextColumn Binding="{Binding FamilyCategory.Name}" Header="族类别" />
|
||||
<DataGridTextColumn Binding="{Binding Name}" Header="族名称" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<GroupBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Header="保存选项">
|
||||
<StackPanel>
|
||||
<RadioButton Content="覆盖存在文件" IsChecked="{Binding IsOverride, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<RadioButton Content="忽略存在文件" />
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center">
|
||||
<CheckBox Content="添加族类别文件夹" IsChecked="{Binding CreateCategoryFolder}" />
|
||||
<CheckBox Content="文件名添加族类别" IsChecked="{Binding AddCategoryPrefix}" />
|
||||
<CheckBox Content="以三维为默认视图" IsChecked="{Binding View3dAsDefault}" />
|
||||
</StackPanel>
|
||||
<ui:TextBox
|
||||
PlaceholderText="保存路径"
|
||||
Text="{Binding PathToSaveFamily}"
|
||||
TextOptions.TextFormattingMode="Display" />
|
||||
<ui:Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding SelectDirectoryCommand}"
|
||||
Content="路径选择"
|
||||
Cursor="Hand"
|
||||
Icon="{ui:FontIcon '',
|
||||
FontFamily={StaticResource BoxIcons}}" />
|
||||
<ComboBox
|
||||
DisplayMemberPath="Title"
|
||||
ItemsSource="{Binding SourceDocsList}"
|
||||
SelectedItem="{Binding SourceDoc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Text="源文档">
|
||||
<!--<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<i:InvokeCommandAction Command="{Binding GetFamiliesCommand}" CommandParameter="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>-->
|
||||
</ComboBox>
|
||||
<ui:Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding SaveFamiliesCommand}"
|
||||
CommandParameter="{Binding SelectedItems, ElementName=FamilySaveDg}"
|
||||
Content="导出保存"
|
||||
Icon="{ui:FontIcon Glyph=,
|
||||
FontFamily={StaticResource BoxIcons}}" />
|
||||
</ui:AutoGridEx>
|
||||
</TabItem>
|
||||
<TabItem Header="传递族">
|
||||
<ui:AutoGridEx
|
||||
ChildMargin="5"
|
||||
Columns="*,Auto"
|
||||
Rows="*,Auto,Auto">
|
||||
<DataGrid
|
||||
x:Name="familyTransmitDg"
|
||||
Grid.ColumnSpan="2"
|
||||
d:ItemsSource="{d:SampleData}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
ItemsSource="{Binding FamilyCollection}"
|
||||
SelectionMode="Extended">
|
||||
<!--<ui:DataGrid.RowHeaderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Width="35">
|
||||
<CheckBox HorizontalAlignment="Center" IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ui:DataGrid.RowHeaderTemplate>-->
|
||||
<DataGrid.Columns>
|
||||
<DataGridCheckBoxColumn
|
||||
Width="60"
|
||||
Binding="{Binding IsSelected, Mode=OneWayToSource, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}"
|
||||
ElementStyle="{StaticResource DataGridCheckBoxElementDefaultStyle}"
|
||||
Header="选择" />
|
||||
<DataGridTextColumn Binding="{Binding FamilyCategory.Name}" Header="族类别" />
|
||||
<DataGridTextColumn Binding="{Binding Name}" Header="族名称" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<ComboBox
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
DisplayMemberPath="Title"
|
||||
ItemsSource="{Binding SourceDocsList, Mode=TwoWay}"
|
||||
SelectedItem="{Binding SourceDoc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
Text="源文档">
|
||||
<!--<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<i:InvokeCommandAction Command="{Binding GetTargetDocListCommand}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>-->
|
||||
</ComboBox>
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Command="{Binding TransmitFamilyCommand}"
|
||||
CommandParameter="{Binding SelectedItems, ElementName=familyTransmitDg}"
|
||||
Content=""
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="传递" />
|
||||
<ComboBox
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
DisplayMemberPath="Title"
|
||||
ItemsSource="{Binding TargetDocsList, Mode=TwoWay}"
|
||||
SelectedItem="{Binding TargetDoc, UpdateSourceTrigger=PropertyChanged}"
|
||||
Text="目标文档" />
|
||||
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Command="{Binding CancelCommand}"
|
||||
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}}"
|
||||
Content=""
|
||||
FontFamily="{StaticResource BoxIcons}"
|
||||
ToolTip="关闭" />
|
||||
</ui:AutoGridEx>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</ui:FluentWindowEx>
|
||||
15
ShrlAlgo.RvKits/RvFamily/FamilyProcessorView.xaml.cs
Normal file
15
ShrlAlgo.RvKits/RvFamily/FamilyProcessorView.xaml.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily
|
||||
{
|
||||
/// <summary>
|
||||
/// WpfMassSaveFamilies.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class FamilyProcessorView
|
||||
{
|
||||
public FamilyProcessorView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
558
ShrlAlgo.RvKits/RvFamily/FamilyProcessorViewModel.cs
Normal file
558
ShrlAlgo.RvKits/RvFamily/FamilyProcessorViewModel.cs
Normal file
@@ -0,0 +1,558 @@
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||||
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using System.Windows;
|
||||
|
||||
using System.Windows.Controls;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
public partial class FamilyProcessorViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool addCategoryPrefix;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool createCategoryFolder;
|
||||
|
||||
[ObservableProperty]
|
||||
private IList<ElementType> familyEditCollection;
|
||||
//private readonly List<TreeModel> familyNodes = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private string findStr;
|
||||
private readonly ActionEventHandler handler;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isOverride = true;
|
||||
|
||||
[ObservableProperty]
|
||||
private int modifyNameIndex;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(SaveFamiliesCommand))]
|
||||
private string pathToSaveFamily;
|
||||
|
||||
[ObservableProperty]
|
||||
private string prefix;
|
||||
|
||||
[ObservableProperty]
|
||||
private string replaceStr;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(TransmitFamilyCommand), nameof(SaveFamiliesCommand))]
|
||||
private Document sourceDoc;
|
||||
|
||||
[ObservableProperty]
|
||||
private string suffix;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(TransmitFamilyCommand))]
|
||||
private Document targetDoc;
|
||||
|
||||
//private readonly ExternalEvent saveEvent;
|
||||
//private readonly SaveFamilyHandler handler;
|
||||
|
||||
//便于类中各处进行调用,故在此处添加字段
|
||||
|
||||
private readonly UIApplication uiapp;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool view3dAsDefault;
|
||||
[ObservableProperty]
|
||||
public List<Family> familyCollection = new();
|
||||
[ObservableProperty]
|
||||
public List<Document> sourceDocsList;
|
||||
|
||||
[ObservableProperty]
|
||||
public List<Document> targetDocsList;
|
||||
|
||||
public FamilyProcessorViewModel(UIApplication uiapp)
|
||||
{
|
||||
this.uiapp = uiapp;
|
||||
handler = new ActionEventHandler();
|
||||
FamilyEditCollection = uiapp.ActiveUIDocument.Document
|
||||
.OfClasses(typeof(HostObjAttributes), typeof(FamilySymbol))
|
||||
.Cast<ElementType>()
|
||||
.ToList();
|
||||
SourceDocsList = AllDocuments;
|
||||
//FamilyEditCollection = uiApplication.ActiveUIDocument.Document.QueryElementTypeByType<ElementType>().Cast<ElementType>().ToList();
|
||||
}
|
||||
|
||||
//private List<TreeModel> AddFamilyToTreeView()
|
||||
//{
|
||||
// List<TreeModel> familiesTree = new();
|
||||
|
||||
// #region 族
|
||||
|
||||
// if (SourceDoc == null)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// var categories = SourceDoc.Settings.Categories;
|
||||
|
||||
// var familyCollector = SourceDoc.OfClass<Family>().Cast<Family>().ToList();
|
||||
|
||||
// var familySymbolCollector = SourceDoc.OfClass<FamilySymbol>().Cast<FamilySymbol>().ToList();
|
||||
|
||||
// //ErrorModels<ElementId> dimensionTypeId = (from ElementToMove i in new FilteredElementCollector(sourceDoc).OfClass(typeof(DimensionType)) select i.ViewId).ToList();
|
||||
// //var elementTypes = new FilteredElementCollector(sourceDoc).OfClass(typeof(ElementType));
|
||||
|
||||
// //ElementClassFilter familysymbolfilter = new ElementClassFilter(typeof(FamilySymbol));
|
||||
// //ElementClassFilter hostsymbolFilter = new ElementClassFilter(typeof(HostObjAttributes));
|
||||
// //LogicalOrFilter andfilter = new LogicalOrFilter(familysymbolfilter, hostsymbolFilter);
|
||||
// //var familiesSymbolCollector = new FilteredElementCollector(sourceDoc).WherePasses(andfilter);
|
||||
// foreach (Category category in categories)
|
||||
// {
|
||||
// TreeModel familyCategoryNode =
|
||||
// new()
|
||||
// {
|
||||
// //familyCategory.ViewId = category.Name;
|
||||
// Name = category.Name,
|
||||
// IsExpanded = false
|
||||
// };
|
||||
|
||||
// foreach (var family in familyCollector)
|
||||
// {
|
||||
// if (family.FamilyCategory.Name == category.Name)
|
||||
// {
|
||||
// TreeModel familyNode =
|
||||
// new()
|
||||
// {
|
||||
// //familyNode.ViewId = family.Name;
|
||||
// Name = family.Name,
|
||||
// IsExpanded = false,
|
||||
// Parent = familyCategoryNode
|
||||
// };
|
||||
// familyCategoryNode.Children.Add(familyNode);
|
||||
|
||||
// //获取族及其族类型,作为加载对象合集
|
||||
// familyNodes.Add(familyNode);
|
||||
// foreach (var familySymbol in familySymbolCollector)
|
||||
// {
|
||||
// if (familySymbol.FamilyName == family.Name)
|
||||
// {
|
||||
// TreeModel familySymbolNode =
|
||||
// new()
|
||||
// {
|
||||
// //familiesSymbolNode.ViewId = familySymbol.Name;
|
||||
// Name = familySymbol.Name,
|
||||
// Parent = familyNode
|
||||
// };
|
||||
// familyNode.Children.Add(familySymbolNode);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (familyCategoryNode.Children.Count != 0)
|
||||
// {
|
||||
// FamilyNodesList.Add(familyCategoryNode);
|
||||
// }
|
||||
// }
|
||||
|
||||
// #endregion 族
|
||||
|
||||
// var hostObjectCollector = new FilteredElementCollector(SourceDoc)
|
||||
// .OfClass(typeof(HostObjAttributes))
|
||||
// .Cast<HostObjAttributes>()
|
||||
// .ToList();
|
||||
// //IList<string> categoryNames = (from HostObjAttributes ele in hostObjectCollector
|
||||
// // select ele.Category.Name).ToList();
|
||||
|
||||
// //var elementTypes = new FilteredElementCollector(sourceDoc).OfClass(typeof(ElementType));
|
||||
// //ErrorModels<string> ss1 = categoryNames.Distinct().ToList();
|
||||
// foreach (var obj in hostObjectCollector)
|
||||
// {
|
||||
// var categoryName = obj.Category.Name;
|
||||
// var familyName = obj.FamilyName;
|
||||
// var familySymbolName = obj.Name;
|
||||
|
||||
// #region categoryRegion
|
||||
|
||||
// TreeModel familyCategoryNode = null;
|
||||
// foreach (var t in familiesTree)
|
||||
// {
|
||||
// if (t.ToolTip.Equals(categoryName)) //遍历是否找到相同的节点
|
||||
// {
|
||||
// familyCategoryNode = t; //有则传递给当前类别节点
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (familyCategoryNode == null)
|
||||
// {
|
||||
// TreeModel t = new() { Name = categoryName, IsExpanded = false };
|
||||
|
||||
// familyCategoryNode = t;
|
||||
// familiesTree.Add(familyCategoryNode);
|
||||
// }
|
||||
|
||||
// #endregion categoryRegion
|
||||
|
||||
// #region familyRegion
|
||||
|
||||
// TreeModel familyNode = null;
|
||||
// foreach (var t in familyCategoryNode.Children)
|
||||
// {
|
||||
// if (t.ToolTip.Equals(categoryName + "-" + familyName))
|
||||
// {
|
||||
// familyNode = t;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (familyNode == null)
|
||||
// {
|
||||
// TreeModel t =
|
||||
// new()
|
||||
// {
|
||||
// Name = familyName,
|
||||
// IsExpanded = false,
|
||||
// Parent = familyCategoryNode
|
||||
// };
|
||||
// familyCategoryNode.Children.Add(t);
|
||||
|
||||
// familyNode = t;
|
||||
|
||||
// familyNodes.Add(familyNode);
|
||||
// }
|
||||
|
||||
// #endregion familyRegion
|
||||
|
||||
// #region familySymbol
|
||||
|
||||
// TreeModel familySymbolNode = null;
|
||||
// foreach (var t in familyNode.Children)
|
||||
// {
|
||||
// if (t.ToolTip.Equals(familyName + "-" + familySymbolName))
|
||||
// {
|
||||
// familySymbolNode = t;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (familySymbolNode == null)
|
||||
// {
|
||||
// TreeModel t =
|
||||
// new()
|
||||
// {
|
||||
// Name = familySymbolName,
|
||||
// IsExpanded = false,
|
||||
// Parent = familyNode
|
||||
// };
|
||||
// familyNode.Children.Add(t);
|
||||
// }
|
||||
|
||||
// #endregion familySymbol
|
||||
|
||||
// //TreeModel familyNode = new TreeModel();
|
||||
// //familyNode.Name = obj.FamilyName;
|
||||
// ////familyNode.Name = obj.FamilyName;
|
||||
// //familyNode.IsExpanded = false;
|
||||
// //familyNode.Parent = categoryNode;
|
||||
// //categoryNode.Children.Add(familyNode);
|
||||
|
||||
// //familyNodes.Add(familyNode);
|
||||
// ////if (obj.Name == familyNode.Name)
|
||||
// ////{
|
||||
// //TreeModel familiesSymbolNode = new TreeModel();
|
||||
// ////familiesSymbolNode.ViewId = familySymbol.Name;
|
||||
// //familiesSymbolNode.Name = obj.Name;
|
||||
// //familiesSymbolNode.Parent = familyNode;
|
||||
// //familyNode.Children.Add(familiesSymbolNode);
|
||||
// //}
|
||||
// }
|
||||
|
||||
// familiesTree.Sort();
|
||||
|
||||
// return familiesTree;
|
||||
// //FamilyTreeView.UpdateLayout();
|
||||
//}
|
||||
|
||||
[RelayCommand]
|
||||
private static void Cancel(object obj)
|
||||
{
|
||||
if (obj is System.Windows.Window window)
|
||||
{
|
||||
window.DialogResult = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前所有文档
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<Document> ListOfOpenedDocument()
|
||||
{
|
||||
var documents = new List<Document>();
|
||||
foreach (Document document in uiapp.Application.Documents)
|
||||
{
|
||||
if (!document.IsLinked && !document.IsFamilyDocument)
|
||||
{
|
||||
documents.Add(document);
|
||||
}
|
||||
}
|
||||
|
||||
return documents;
|
||||
}
|
||||
|
||||
partial void OnSourceDocChanged(Document value)
|
||||
{
|
||||
FamilyCollection = SourceDoc.OfClass<Family>().OfType<Family>().Where(f => f.IsEditable).ToList();
|
||||
TargetDocsList = new(
|
||||
AllDocuments.Where(
|
||||
d =>
|
||||
(d.PathName != null && SourceDoc?.PathName != null && d.PathName != SourceDoc.PathName)
|
||||
|| (SourceDoc != null && d.Title != SourceDoc.Title)
|
||||
|| SourceDoc == null
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanSaveFamilies))]
|
||||
private void SaveFamilies(object obj)
|
||||
{
|
||||
var items = (System.Collections.IList)obj;
|
||||
var collection = items.Cast<Family>();
|
||||
var selectedItems = collection.ToList();
|
||||
if (!selectedItems.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
handler.Raise(_ =>
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
if (!Directory.Exists(PathToSaveFamily))
|
||||
{
|
||||
var dr = MessageBox.Show("路径不存在,是否创建该路径", "提示", MessageBoxButton.OKCancel, MessageBoxImage.Information);
|
||||
if (dr == MessageBoxResult.OK)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(PathToSaveFamily);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Message.ToLog();
|
||||
MessageBox.Show("无法创建保存路径", "错误", MessageBoxButton.YesNo, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//FileInfo fileInfo = new FileInfo(text3);
|
||||
foreach (var family in selectedItems)
|
||||
{
|
||||
var familyFileInfo = family.Name;
|
||||
//string categoryInfo = family.Category.Name;
|
||||
|
||||
var directory = PathToSaveFamily + "\\";
|
||||
var categoryInfo = family.FamilyCategory.Name;
|
||||
|
||||
if (CreateCategoryFolder)
|
||||
{
|
||||
directory += $"{categoryInfo}\\";
|
||||
DirectoryInfo directoryInfo = new(directory);
|
||||
if (!directoryInfo.Exists)
|
||||
{
|
||||
directoryInfo.Create();
|
||||
}
|
||||
}
|
||||
|
||||
if (AddCategoryPrefix)
|
||||
{
|
||||
familyFileInfo = $"({categoryInfo}){familyFileInfo}";
|
||||
}
|
||||
|
||||
var completeDir = directory + familyFileInfo + ".rfa";
|
||||
|
||||
try
|
||||
{
|
||||
FileInfo fileInfo = new(completeDir);
|
||||
if (fileInfo.Exists)
|
||||
{
|
||||
if (IsOverride)
|
||||
{
|
||||
fileInfo.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
if (family.IsEditable)
|
||||
{
|
||||
var editFamily = SourceDoc.EditFamily(family);
|
||||
if (View3dAsDefault)
|
||||
{
|
||||
Set3DView(editFamily);
|
||||
}
|
||||
|
||||
editFamily.SaveAs(completeDir);
|
||||
editFamily.Close(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine($"{categoryInfo}-{family.Name}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty($"{sb}"))
|
||||
{
|
||||
MessageBox.Show($"以下族无法导出:\n{sb}", "导出错误", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
});
|
||||
//saveEvent.Raise();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SelectDirectory()
|
||||
{
|
||||
WPFluent.Controls.VistaFolderBrowserDialog dialog = new();
|
||||
//dialog.Description = "请选择文件路径";
|
||||
//dialog.SeletcedPath = @"C:\Users\ZGG\Documents";
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
var savePath = dialog.SelectedPath;
|
||||
PathToSaveFamily = savePath;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Set3DView(Document doc)
|
||||
{
|
||||
try
|
||||
{
|
||||
Transaction transaction = new(doc);
|
||||
transaction.Start();
|
||||
doc.GetDocumentPreviewSettings();
|
||||
SaveAsOptions saveAsOptions = new();
|
||||
if (doc.GetDocumentPreviewSettings().PreviewViewId.Equals(ElementId.InvalidElementId))
|
||||
{
|
||||
var startingViewSettings = StartingViewSettings.GetStartingViewSettings(doc);
|
||||
if (!startingViewSettings.ViewId.Equals(ElementId.InvalidElementId))
|
||||
{
|
||||
saveAsOptions.PreviewViewId = startingViewSettings.ViewId;
|
||||
}
|
||||
else
|
||||
{
|
||||
var viewCollector = new FilteredElementCollector(doc).OfClass(typeof(View));
|
||||
var viewEnum = viewCollector
|
||||
.Cast<View>()
|
||||
.Where(view => view.ViewType == ViewType.ThreeD && !view.IsTemplate);
|
||||
var flag = true;
|
||||
foreach (View view in (IEnumerable)viewEnum)
|
||||
{
|
||||
if (view.IsTemplate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
saveAsOptions.PreviewViewId = view.Id;
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
foreach (
|
||||
View view in (IEnumerable)
|
||||
viewCollector
|
||||
.Cast<View>()
|
||||
.Where(viewNot3D =>
|
||||
{
|
||||
return viewNot3D.ViewType
|
||||
is ViewType.FloorPlan
|
||||
or ViewType.EngineeringPlan
|
||||
or ViewType.Elevation
|
||||
|| (viewNot3D.ViewType == ViewType.Section && !viewNot3D.IsTemplate);
|
||||
})
|
||||
)
|
||||
{
|
||||
if (view.IsTemplate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
saveAsOptions.PreviewViewId = view.Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transaction.Commit();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanTransmitFamilies))]
|
||||
private void TransmitFamily(object obj)
|
||||
{
|
||||
var items = (IList)obj;
|
||||
var collection = items.Cast<Family>();
|
||||
var selectedItems = collection.ToList();
|
||||
if (!selectedItems.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
handler.Raise(_ =>
|
||||
{
|
||||
TargetDoc.Invoke(
|
||||
_ =>
|
||||
{
|
||||
CopyPasteOptions copyPasteOptions = new();
|
||||
//copyPasteOptions.SetDuplicateTypeNamesHandler(copyPasteOptions.GetDuplicateTypeNamesHandler());
|
||||
var ids = selectedItems.ConvertAll(f => f.Id);
|
||||
ElementTransformUtils.CopyElements(SourceDoc, ids, TargetDoc, null, copyPasteOptions);
|
||||
},
|
||||
"传递族"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private List<Document> AllDocuments => ListOfOpenedDocument();
|
||||
|
||||
private bool CanSaveFamilies => PathToSaveFamily != null && SourceDoc != null;
|
||||
|
||||
private bool CanTransmitFamilies => SourceDoc != null && TargetDoc != null;
|
||||
|
||||
}
|
||||
|
||||
//public class CopyHandlerOk : IDuplicateTypeNamesHandler
|
||||
//{
|
||||
// public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args)
|
||||
// {
|
||||
// return DuplicateTypeAction.UseDestinationTypes;
|
||||
// }
|
||||
//}
|
||||
|
||||
//public class CopyHandlerAbort : IDuplicateTypeNamesHandler
|
||||
//{
|
||||
// public DuplicateTypeAction OnDuplicateTypeNamesFound(DuplicateTypeNamesHandlerArgs args)
|
||||
// {
|
||||
// return DuplicateTypeAction.Abort;
|
||||
// }
|
||||
//}
|
||||
32
ShrlAlgo.RvKits/RvFamily/RenameFamilyItem.cs
Normal file
32
ShrlAlgo.RvKits/RvFamily/RenameFamilyItem.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
using ShrlAlgo.Toolkit.Mvvm.Attributes;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
public partial class RenameFamilyItem : ObservableValidator
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool isSelected;
|
||||
|
||||
[ObservableProperty]
|
||||
[UndefinedChar]
|
||||
[NotifyDataErrorInfo]
|
||||
private string newFamilyName;
|
||||
|
||||
[ObservableProperty]
|
||||
private string oldFamilyName;
|
||||
|
||||
partial void OnIsSelectedChanged(bool value)
|
||||
{
|
||||
if (value == false)
|
||||
{
|
||||
NewFamilyName = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public Family Family { get; set; }
|
||||
public string CategoryName { get; set; }
|
||||
}
|
||||
27
ShrlAlgo.RvKits/RvFamily/RenameFamilyNameCmd.cs
Normal file
27
ShrlAlgo.RvKits/RvFamily/RenameFamilyNameCmd.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
using System;
|
||||
|
||||
using System.Windows;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily
|
||||
{
|
||||
/// <summary>
|
||||
/// Revit执行命令
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class RenameFamilyNameCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
RenameFamilyViewModel viewmodel = new(UiApplication);
|
||||
RenameFamilyView win = new(viewmodel);
|
||||
win.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
269
ShrlAlgo.RvKits/RvFamily/RenameFamilyView.xaml
Normal file
269
ShrlAlgo.RvKits/RvFamily/RenameFamilyView.xaml
Normal file
@@ -0,0 +1,269 @@
|
||||
<ui:FluentWindowEx
|
||||
x:Class="ShrlAlgo.RvKits.RvFamily.RenameFamilyView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
|
||||
xmlns:local="clr-namespace:ShrlAlgo.RvKits.RvFamily"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="https://github.com/ShrlAlgo/WPFluent"
|
||||
xmlns:attachedProps="clr-namespace:ShrlAlgo.Toolkit.Mvvm.AttachedProps"
|
||||
xmlns:validationRules="clr-namespace:ShrlAlgo.Toolkit.Mvvm.ValidationRules"
|
||||
Title="重命名族"
|
||||
Width="900"
|
||||
Height="600"
|
||||
d:DataContext="{d:DesignInstance local:RenameFamilyViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary Source="pack://application:,,,/ShrlAlgo.RvKits;component/WPFUI.xaml" />
|
||||
</Window.Resources>
|
||||
<ui:AutoGridEx
|
||||
ChildMargin="5"
|
||||
Columns="250,*,*,*"
|
||||
Rows="*,Auto">
|
||||
<ui:AutoGridEx
|
||||
Grid.RowSpan="2"
|
||||
Columns="*"
|
||||
Rows="*,Auto,Auto">
|
||||
<GroupBox Header="族类别">
|
||||
<ListBox
|
||||
x:Name="LbCategories"
|
||||
Height="400"
|
||||
d:ItemsSource="{d:SampleData ItemCount=5}"
|
||||
DisplayMemberPath="Key"
|
||||
ItemsSource="{Binding Collection, Mode=OneWay}"
|
||||
SelectionMode="Multiple">
|
||||
<!--<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>-->
|
||||
<!--<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>-->
|
||||
<!--<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border CornerRadius="5" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>-->
|
||||
<!--<ListBox.ItemContainerStyle>
|
||||
<Style />
|
||||
</ListBox.ItemContainerStyle>-->
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="SelectionChanged">
|
||||
<b:InvokeCommandAction Command="{Binding GetRenameItemsCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ListBox}, Mode=FindAncestor}}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
<!--<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" />
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Value}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>-->
|
||||
</ListBox>
|
||||
</GroupBox>
|
||||
<DockPanel>
|
||||
<CheckBox Content="全选">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="Checked">
|
||||
<b:CallMethodAction MethodName="SelectAll" TargetObject="{Binding ElementName=LbCategories}" />
|
||||
</b:EventTrigger>
|
||||
<b:EventTrigger EventName="Unchecked">
|
||||
<b:CallMethodAction MethodName="UnselectAll" TargetObject="{Binding ElementName=LbCategories}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
</CheckBox>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding CategoryCount, StringFormat=类别数:{}{0:D}}" />
|
||||
</DockPanel>
|
||||
<ui:TextBoxEx PlaceholderText="过滤族类别" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</ui:AutoGridEx>
|
||||
<DataGrid
|
||||
x:Name="DgRename"
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="3"
|
||||
attachedProps:TextSearch.SearchValue="{Binding Text, ElementName=TbFound, UpdateSourceTrigger=PropertyChanged}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
HeadersVisibility="Column"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
ItemsSource="{Binding RenameItems}"
|
||||
SelectionUnit="Cell">
|
||||
<DataGrid.Resources>
|
||||
<Style BasedOn="{StaticResource DefaultDataGridCellStyle}" TargetType="{x:Type DataGridCell}">
|
||||
<!--<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />-->
|
||||
<Setter Property="attachedProps:TextSearch.IsTextMatch">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource SearchFamilyValueConverter}">
|
||||
<Binding Path="Content.Text" RelativeSource="{RelativeSource Mode=Self}" />
|
||||
<Binding Path="(attachedProps:TextSearch.SearchValue)" RelativeSource="{RelativeSource Mode=Self}" />
|
||||
<Binding RelativeSource="{RelativeSource Mode=Self}" />
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="attachedProps:TextSearch.IsTextMatch" Value="True">
|
||||
<Setter Property="Foreground" Value="SkyBlue" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGrid.Resources>
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style BasedOn="{StaticResource DefaultDataGridColumnHeaderStyle}" TargetType="{x:Type DataGridColumnHeader}">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridCheckBoxColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"
|
||||
EditingElementStyle="{StaticResource DataGridCheckBoxEditingElementDefaultStyle}"
|
||||
ElementStyle="{StaticResource DataGridCheckBoxElementDefaultStyle}">
|
||||
<DataGridCheckBoxColumn.Header>
|
||||
<Border Background="Transparent">
|
||||
<CheckBox
|
||||
HorizontalAlignment="Center"
|
||||
Content="全选"
|
||||
IsChecked="{Binding DataContext.IsAllItemsSelected, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
|
||||
</Border>
|
||||
</DataGridCheckBoxColumn.Header>
|
||||
<!--<DataGridCheckBoxColumn.HeaderStyle>
|
||||
<Style BasedOn="{StaticResource DefaultDataGridColumnHeaderStyle}" TargetType="{x:Type DataGridColumnHeader}">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridCheckBoxColumn.HeaderStyle>-->
|
||||
</DataGridCheckBoxColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding CategoryName}"
|
||||
Header="族类别"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding OldFamilyName}"
|
||||
Header="族名称"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding NewFamilyName, UpdateSourceTrigger=PropertyChanged}"
|
||||
EditingElementStyle="{StaticResource DefaultTextBoxStyle}"
|
||||
Header="新族名称">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<GroupBox Header="前/后缀">
|
||||
<UniformGrid Columns="1">
|
||||
<ui:TextBox
|
||||
x:Name="CbPrefix"
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="前缀">
|
||||
<Binding Path="PrefixText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
<!--<TextBox
|
||||
x:Name="TbPrefix"
|
||||
materialDesign:HintAssist.Hint="前缀"
|
||||
IsEnabled="{Binding CanInput}">
|
||||
<TextBox.Text>
|
||||
<Binding Path="PrefixText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox.Text>
|
||||
</TextBox>-->
|
||||
<ui:TextBox
|
||||
x:Name="TbSuffix"
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="后缀">
|
||||
<Binding Path="SuffixText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="查找/替换">
|
||||
<StackPanel>
|
||||
<ui:TextBox
|
||||
x:Name="TbFound"
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="查找">
|
||||
<Binding Path="FoundText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
<ui:TextBox
|
||||
x:Name="TbReplace"
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="替换">
|
||||
<Binding Path="ReplaceText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<GroupBox Grid.Row="0" Header="连接符">
|
||||
<TextBox x:Name="TbSeparator" IsEnabled="{Binding CanInput}">
|
||||
<Binding Path="Separator" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox>
|
||||
</GroupBox>
|
||||
<Button
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding ModifyNameCommand}"
|
||||
Content="修改名称"
|
||||
ToolTip="勾选要修改的项进行修改" />
|
||||
</Grid>
|
||||
</ui:AutoGridEx>
|
||||
</ui:FluentWindowEx>
|
||||
17
ShrlAlgo.RvKits/RvFamily/RenameFamilyView.xaml.cs
Normal file
17
ShrlAlgo.RvKits/RvFamily/RenameFamilyView.xaml.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily
|
||||
{
|
||||
/// <summary>
|
||||
/// RenameFamilyView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class RenameFamilyView
|
||||
{
|
||||
public RenameFamilyView(RvFamily.RenameFamilyViewModel familyViewModel)
|
||||
{
|
||||
DataContext = familyViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
323
ShrlAlgo.RvKits/RvFamily/RenameFamilyViewModel.cs
Normal file
323
ShrlAlgo.RvKits/RvFamily/RenameFamilyViewModel.cs
Normal file
@@ -0,0 +1,323 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
public partial class RenameFamilyViewModel : ObservableObject
|
||||
{
|
||||
public RenameFamilyViewModel(UIApplication uiApplication)
|
||||
{
|
||||
doc = uiApplication.ActiveUIDocument.Document;
|
||||
allCategories = GetCategoriesFromDocument();
|
||||
Collection = allCategories;
|
||||
|
||||
//ICollectionView cv = CollectionViewSource.GetDefaultView(Categories);
|
||||
//cv.Filter = item => string.IsNullOrEmpty(SearchText) ||
|
||||
// ((KeyValuePair<BuiltInCategory, string>)item).Value.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
//TaskDialog.Show("数量", CategoriesDictionary.Count.ToString());
|
||||
}
|
||||
|
||||
//[ObservableProperty]
|
||||
//private List<BuiltInCategory> selectedBuiltInCategories;
|
||||
private readonly Dictionary<string, List<Family>> allCategories;
|
||||
|
||||
//public ICollectionView CategoriesCollectionView { get; set; }
|
||||
private readonly Document doc;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool canInput;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isRunning;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isUsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Dictionary<string, List<Family>> collection;
|
||||
|
||||
[ObservableProperty]
|
||||
private int categoryCount;
|
||||
/// <summary>
|
||||
/// 列表中元素
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(ModifyNameCommand))]
|
||||
private List<RenameFamilyItem> renameItems;
|
||||
|
||||
[ObservableProperty]
|
||||
private string foundText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string prefixText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string replaceText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string searchText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string separator = "-";
|
||||
|
||||
[ObservableProperty]
|
||||
private string suffixText;
|
||||
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||
public bool CanModify => RenameItems?.Any(item => item.IsSelected) == true;
|
||||
|
||||
public bool? IsAllItemsSelected
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RenameItems == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var selected = RenameItems.Select(item => item.IsSelected).Distinct().ToList();
|
||||
return selected?.Count == 1 ? selected.Single() : null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
SelectAll(value.Value, RenameItems);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
partial void OnIsUsedChanged(bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
var collector = doc.OfCollector().WhereElementIsNotElementType();
|
||||
foreach (var item in RenameItems)
|
||||
{
|
||||
foreach (var id in item.Family.GetFamilySymbolIds())
|
||||
{
|
||||
var b = collector.Any(e => e.GetTypeId() == id);
|
||||
if (b)
|
||||
{
|
||||
item.IsSelected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public Dictionary<string, List<Family>> GetCategoriesFromDocument()
|
||||
{
|
||||
var dict = new FilteredElementCollector(doc)
|
||||
.OfClass(typeof(Family))
|
||||
.Cast<Family>()
|
||||
.Where(f => f.FamilyCategory is { CategoryType: CategoryType.Model or CategoryType.Annotation, AllowsBoundParameters: true })
|
||||
.GroupBy(f => f.FamilyCategory.Id)
|
||||
.ToDictionary(g => Category.GetCategory(doc, g.Key).Name, g => g.ToList());
|
||||
CategoryCount = dict.Count;
|
||||
return dict;
|
||||
//foreach (BuiltInCategory builtInCategory in Enum.GetValues(typeof(BuiltInCategory)))
|
||||
//{
|
||||
// Category category = Category.GetCategory(doc, builtInCategory);
|
||||
// if (category is
|
||||
// {
|
||||
// CategoryType: CategoryType.Model or CategoryType.Annotation,
|
||||
// AllowsBoundParameters: true
|
||||
// })
|
||||
// {
|
||||
// var familyType = new FilteredElementCollector(doc)
|
||||
// .QueryElementsByType(typeof(Family))
|
||||
// .OfCategory(builtInCategory)
|
||||
// .Cast<Family>()
|
||||
// .ToList();
|
||||
// if (familyType.Any())
|
||||
// {
|
||||
// var name = category.Name;
|
||||
// items.Add(builtInCategory, name);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//CategoryCount = items.Count;
|
||||
//return items.OrderBy(kv => kv.Value).ToDictionary(kv => kv.Key, kv => kv.Value);
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanModify))]
|
||||
private async Task ModifyName()
|
||||
{
|
||||
await Task.Delay(1_000);
|
||||
ModifyFamilyName();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取列表中所有条目的新名称
|
||||
/// </summary>
|
||||
private void GetNewNames()
|
||||
{
|
||||
var selectedItems = RenameItems.Where(item => item.IsSelected);
|
||||
foreach (var renameItem in selectedItems)
|
||||
{
|
||||
var tempName = renameItem.OldFamilyName;
|
||||
//手动修改的新名称不处理
|
||||
if (!string.IsNullOrEmpty(renameItem.NewFamilyName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(FoundText))
|
||||
{
|
||||
tempName = tempName.Replace(FoundText, string.IsNullOrEmpty(ReplaceText) ? string.Empty : ReplaceText);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(PrefixText))
|
||||
{
|
||||
tempName = tempName.Insert(0, $"{PrefixText}{Separator}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(SuffixText))
|
||||
{
|
||||
tempName += $"{Separator}{SuffixText}";
|
||||
}
|
||||
|
||||
renameItem.NewFamilyName = tempName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取重命名的条目
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
[RelayCommand]
|
||||
private void GetRenameItems(IList items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
RenameItems = null!;
|
||||
CanInput = false;
|
||||
return;
|
||||
}
|
||||
|
||||
List<RenameFamilyItem> familyItems = new();
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is KeyValuePair<string, List<Family>> categoryItems)
|
||||
{
|
||||
//var familyType = new FilteredElementCollector(doc)
|
||||
// .QueryElementsByType(typeof(Family))
|
||||
// .Cast<Family>()
|
||||
// .Where(
|
||||
// f => f.FamilyCategory.Id.IntegerValue == new ElementId(categoryItem.Key).IntegerValue
|
||||
// );
|
||||
|
||||
foreach (var family in categoryItems.Value)
|
||||
{
|
||||
RenameFamilyItem renameItem =
|
||||
new()
|
||||
{
|
||||
OldFamilyName = family.Name,
|
||||
Family = family,
|
||||
CategoryName = categoryItems.Key
|
||||
};
|
||||
|
||||
familyItems.Add(renameItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CanInput = familyItems.Any();
|
||||
RenameItems = familyItems;
|
||||
//IsAllItemsSelected = true;
|
||||
foreach (var renameItem in RenameItems)
|
||||
{
|
||||
renameItem.PropertyChanged += (sender, args) =>
|
||||
{
|
||||
//选中属性修改时,触发
|
||||
if (args.PropertyName == nameof(RenameFamilyItem.IsSelected))
|
||||
{
|
||||
OnPropertyChanged(nameof(IsAllItemsSelected));
|
||||
ModifyNameCommand.NotifyCanExecuteChanged();
|
||||
if (string.IsNullOrEmpty(renameItem.NewFamilyName))
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
}
|
||||
//单个修改名称时
|
||||
//if (args.PropertyName == nameof(RenameFamilyItem.NewFamilyName))
|
||||
//{
|
||||
// ModifyFamilyName();
|
||||
//}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改族名称
|
||||
/// </summary>
|
||||
private void ModifyFamilyName()
|
||||
{
|
||||
var needToRename = RenameItems.Where(item => item.IsSelected);
|
||||
using Transaction ts = new(doc, "修改族名称");
|
||||
ts.Start();
|
||||
|
||||
foreach (var renameItem in needToRename)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(renameItem.NewFamilyName))
|
||||
{
|
||||
renameItem.Family.Name = renameItem.NewFamilyName;
|
||||
renameItem.OldFamilyName = renameItem.NewFamilyName;
|
||||
}
|
||||
}
|
||||
|
||||
ts.Commit();
|
||||
}
|
||||
|
||||
partial void OnFoundTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnPrefixTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnReplaceTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnSearchTextChanged(string value)
|
||||
{
|
||||
Collection = allCategories
|
||||
.Where(kv => string.IsNullOrEmpty(value) || kv.Key.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
.ToDictionary(k => k.Key, v => v.Value);
|
||||
CategoryCount = Collection.Count;
|
||||
//CategoriesCollectionView.Refresh();
|
||||
}
|
||||
|
||||
partial void OnSeparatorChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnSuffixTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
private static void SelectAll(bool select, IEnumerable<RenameFamilyItem> models)
|
||||
{
|
||||
foreach (var model in models)
|
||||
{
|
||||
model.IsSelected = select;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
ShrlAlgo.RvKits/RvFamily/RenameTypeItem.cs
Normal file
42
ShrlAlgo.RvKits/RvFamily/RenameTypeItem.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Autodesk.Revit.DB;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
using ShrlAlgo.Toolkit.Mvvm.Attributes;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
public partial class RenameTypeItem : ObservableValidator
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool isSelected;
|
||||
|
||||
[ObservableProperty]
|
||||
[UndefinedChar]
|
||||
[NotifyDataErrorInfo]
|
||||
private string newTypeName;
|
||||
|
||||
[ObservableProperty]
|
||||
private string oldTypeName;
|
||||
|
||||
partial void OnIsSelectedChanged(bool value)
|
||||
{
|
||||
if (value == false)
|
||||
{
|
||||
NewTypeName = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public ElementType ElementType { get; set; }
|
||||
public string CategoryName { get; set; }
|
||||
public string FamilyName { get; set; }
|
||||
|
||||
//public RenameTypeItem()
|
||||
//{
|
||||
// PropertyChanged += (sender, args) =>
|
||||
// {
|
||||
// if (args.PropertyName == nameof(RenameTypeItem.IsSelected))
|
||||
// OnPropertyChanged(nameof(RenameTypeViewModel.IsAllItemsSelected));
|
||||
// };
|
||||
//}
|
||||
}
|
||||
28
ShrlAlgo.RvKits/RvFamily/RenameTypeNameCmd.cs
Normal file
28
ShrlAlgo.RvKits/RvFamily/RenameTypeNameCmd.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
using System;
|
||||
|
||||
using System.Windows;
|
||||
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily
|
||||
{
|
||||
/// <summary>
|
||||
/// Revit执行命令
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class RenameTypeNameCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
RenameTypeViewModel viewmodel = new(UiApplication);
|
||||
RenameTypeView win = new(viewmodel);
|
||||
win.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
252
ShrlAlgo.RvKits/RvFamily/RenameTypeView.xaml
Normal file
252
ShrlAlgo.RvKits/RvFamily/RenameTypeView.xaml
Normal file
@@ -0,0 +1,252 @@
|
||||
<ui:FluentWindowEx
|
||||
x:Class="ShrlAlgo.RvKits.RvFamily.RenameTypeView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
|
||||
xmlns:local="clr-namespace:ShrlAlgo.RvKits.RvFamily"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="https://github.com/ShrlAlgo/WPFluent"
|
||||
xmlns:attachedProps="clr-namespace:ShrlAlgo.Toolkit.Mvvm.AttachedProps"
|
||||
xmlns:validationRules="clr-namespace:ShrlAlgo.Toolkit.Mvvm.ValidationRules"
|
||||
Title="重命名族类型"
|
||||
Width="900"
|
||||
Height="600"
|
||||
d:DataContext="{d:DesignInstance local:RenameTypeViewModel}"
|
||||
mc:Ignorable="d">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary Source="pack://application:,,,/ShrlAlgo.RvKits;component/WPFUI.xaml" />
|
||||
</Window.Resources>
|
||||
<ui:AutoGridEx
|
||||
ChildMargin="5"
|
||||
Columns="250,*,*,*"
|
||||
Rows="*,Auto">
|
||||
<ui:AutoGridEx
|
||||
Grid.RowSpan="2"
|
||||
Columns="*"
|
||||
Rows="*,Auto,Auto">
|
||||
<GroupBox Header="族类别">
|
||||
<ListBox
|
||||
x:Name="LbCategories"
|
||||
d:ItemsSource="{d:SampleData ItemCount=5}"
|
||||
DisplayMemberPath="Key"
|
||||
ItemsSource="{Binding Collection, Mode=OneWay}"
|
||||
SelectionMode="Multiple">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="SelectionChanged">
|
||||
<b:InvokeCommandAction Command="{Binding GetRenameItemsCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ListBox}, Mode=FindAncestor}}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
<!--<ListBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<ui:VirtualizingWrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ListBox.ItemsPanel>-->
|
||||
<!--<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=ListBoxItem}}" />
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Value}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>-->
|
||||
</ListBox>
|
||||
</GroupBox>
|
||||
<DockPanel Margin="5,503,5,40">
|
||||
<CheckBox Content="全选" DockPanel.Dock="Left">
|
||||
<b:Interaction.Triggers>
|
||||
<b:EventTrigger EventName="Checked">
|
||||
<b:CallMethodAction MethodName="SelectAll" TargetObject="{Binding ElementName=LbCategories}" />
|
||||
</b:EventTrigger>
|
||||
<b:EventTrigger EventName="Unchecked">
|
||||
<b:CallMethodAction MethodName="UnselectAll" TargetObject="{Binding ElementName=LbCategories}" />
|
||||
</b:EventTrigger>
|
||||
</b:Interaction.Triggers>
|
||||
</CheckBox>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center"
|
||||
DockPanel.Dock="Right"
|
||||
Text="{Binding CategoryCount, StringFormat=类别个数:\{0:D\}}" />
|
||||
</DockPanel>
|
||||
<ui:TextBox
|
||||
Margin="5,535,5,5"
|
||||
PlaceholderText="过滤族类别"
|
||||
Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" />
|
||||
</ui:AutoGridEx>
|
||||
<DataGrid
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="3"
|
||||
attachedProps:TextSearch.SearchValue="{Binding Text, ElementName=TbFound, UpdateSourceTrigger=PropertyChanged}"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
HeadersVisibility="Column"
|
||||
ItemsSource="{Binding RenameItems}"
|
||||
SelectionMode="Extended"
|
||||
SelectionUnit="Cell">
|
||||
<DataGrid.Resources>
|
||||
<Style BasedOn="{StaticResource DefaultDataGridCellStyle}" TargetType="{x:Type DataGridCell}">
|
||||
<Setter Property="attachedProps:TextSearch.IsTextMatch">
|
||||
<Setter.Value>
|
||||
<MultiBinding Converter="{StaticResource SearchTypeValueConverter}">
|
||||
<Binding Path="Content.Text" RelativeSource="{RelativeSource Mode=Self}" />
|
||||
<Binding Path="(attachedProps:TextSearch.SearchValue)" RelativeSource="{RelativeSource Mode=Self}" />
|
||||
<Binding RelativeSource="{RelativeSource Mode=Self}" />
|
||||
</MultiBinding>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="attachedProps:TextSearch.IsTextMatch" Value="True">
|
||||
<Setter Property="Foreground" Value="SkyBlue" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGrid.Resources>
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style BasedOn="{StaticResource DefaultDataGridColumnHeaderStyle}" TargetType="{x:Type DataGridColumnHeader}">
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridCheckBoxColumn
|
||||
Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"
|
||||
EditingElementStyle="{StaticResource DataGridCheckBoxEditingElementDefaultStyle}"
|
||||
ElementStyle="{StaticResource DataGridCheckBoxElementDefaultStyle}">
|
||||
<DataGridCheckBoxColumn.Header>
|
||||
<CheckBox
|
||||
HorizontalAlignment="Center"
|
||||
Content="全选"
|
||||
IsChecked="{Binding DataContext.IsAllItemsSelected, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
|
||||
</DataGridCheckBoxColumn.Header>
|
||||
</DataGridCheckBoxColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding CategoryName}"
|
||||
Header="族类别"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding FamilyName}"
|
||||
Header="族名称"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding OldTypeName}"
|
||||
Header="族类型"
|
||||
IsReadOnly="True">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
<DataGridTextColumn
|
||||
MinWidth="80"
|
||||
Binding="{Binding NewTypeName, UpdateSourceTrigger=PropertyChanged}"
|
||||
EditingElementStyle="{StaticResource DefaultTextBoxStyle}"
|
||||
Header="新族类型名称">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<GroupBox Header="前/后缀">
|
||||
<UniformGrid Columns="1">
|
||||
<ui:TextBox
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="前缀">
|
||||
<Binding Path="PrefixText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
<ui:TextBox
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="后缀">
|
||||
<Binding Path="SuffixText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
<GroupBox Header="查找/替换">
|
||||
<UniformGrid Columns="1">
|
||||
<ui:TextBox
|
||||
x:Name="TbFound"
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="查找">
|
||||
<Binding Path="FoundText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
<ui:TextBox
|
||||
x:Name="TbReplace"
|
||||
Margin="5"
|
||||
IsEnabled="{Binding CanInput}"
|
||||
PlaceholderText="替换">
|
||||
<Binding Path="ReplaceText" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</ui:TextBox>
|
||||
</UniformGrid>
|
||||
</GroupBox>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<GroupBox Grid.Row="0" Header="分隔符">
|
||||
<TextBox x:Name="TbSeparator" IsEnabled="{Binding CanInput}">
|
||||
<Binding Path="Separator" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
<validationRules:UndefinedCharRules ValidatesOnTargetUpdated="True" />
|
||||
</Binding.ValidationRules>
|
||||
</Binding>
|
||||
</TextBox>
|
||||
</GroupBox>
|
||||
<!--
|
||||
materialDesign:ButtonProgressAssist.IsIndeterminate="{Binding ModifyNameCommand.IsRunning, Mode=OneWay}"
|
||||
materialDesign:ButtonProgressAssist.IsIndicatorVisible="{Binding ModifyNameCommand.IsRunning, Mode=OneWay}"
|
||||
materialDesign:ButtonProgressAssist.Value="-1"
|
||||
-->
|
||||
<ui:Button
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Command="{Binding ModifyNameCommand}"
|
||||
Content="修改名称"
|
||||
ToolTip="勾选要修改的项进行修改" />
|
||||
</Grid>
|
||||
</ui:AutoGridEx>
|
||||
</ui:FluentWindowEx>
|
||||
16
ShrlAlgo.RvKits/RvFamily/RenameTypeView.xaml.cs
Normal file
16
ShrlAlgo.RvKits/RvFamily/RenameTypeView.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily
|
||||
{
|
||||
/// <summary>
|
||||
/// RenameFamilyView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class RenameTypeView
|
||||
{
|
||||
public RenameTypeView(RenameTypeViewModel typeViewModel)
|
||||
{
|
||||
DataContext = typeViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
306
ShrlAlgo.RvKits/RvFamily/RenameTypeViewModel.cs
Normal file
306
ShrlAlgo.RvKits/RvFamily/RenameTypeViewModel.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using System.Collections;
|
||||
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
public partial class RenameTypeViewModel : ObservableObject
|
||||
{
|
||||
public RenameTypeViewModel(UIApplication uiApplication)
|
||||
{
|
||||
doc = uiApplication.ActiveUIDocument.Document;
|
||||
allCategories = GetCategoriesFromDocument();
|
||||
Collection = allCategories;
|
||||
//ICollectionView cv = CollectionViewSource.GetDefaultView(Categories);
|
||||
//cv.Filter = item => string.IsNullOrEmpty(SearchText) ||
|
||||
// ((KeyValuePair<BuiltInCategory, string>)item).Value.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
//TaskDialog.Show("数量", CategoriesDictionary.Count.ToString());
|
||||
}
|
||||
|
||||
//[ObservableProperty]
|
||||
//private List<BuiltInCategory> selectedBuiltInCategories;
|
||||
private readonly Dictionary<string, List<ElementType>> allCategories;
|
||||
|
||||
//public ICollectionView CategoriesCollectionView { get; set; }
|
||||
private readonly Document doc;
|
||||
/// <summary>
|
||||
/// 列表中元素
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(ModifyNameCommand))]
|
||||
//[NotifyPropertyChangedFor(nameof(IsAllItemsSelected))]
|
||||
private List<RenameTypeItem> renameItems;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool canInput;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isRunning;
|
||||
|
||||
/// <summary>
|
||||
/// 选中正在使用中的条目
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private bool isUsed;
|
||||
|
||||
[ObservableProperty]
|
||||
private Dictionary<string, List<ElementType>> collection;
|
||||
|
||||
[ObservableProperty]
|
||||
private int categoryCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private int modifyType;
|
||||
|
||||
[ObservableProperty]
|
||||
private string foundText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string prefixText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string replaceText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string searchText;
|
||||
|
||||
[ObservableProperty]
|
||||
private string separator = "-";
|
||||
|
||||
[ObservableProperty]
|
||||
private string suffixText;
|
||||
|
||||
//[ObservableProperty]
|
||||
//private IList selectedItems;
|
||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
||||
public bool CanModify => RenameItems != null && RenameItems.Any(item => item.IsSelected);
|
||||
//[ObservableProperty]
|
||||
//private bool? isAllItemsSelected;
|
||||
|
||||
//partial void OnIsAllItemsSelectedChanged(bool? value)
|
||||
//{
|
||||
// if (value.HasValue)
|
||||
// {
|
||||
// SelectAll(value.Value, RenameItems);
|
||||
// }
|
||||
//}
|
||||
|
||||
public bool? IsAllItemsSelected
|
||||
{
|
||||
get
|
||||
{
|
||||
if (RenameItems == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var selected = RenameItems?.Select(item => item.IsSelected).Distinct().ToList();
|
||||
return selected?.Count == 1 ? selected.Single() : null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.HasValue)
|
||||
{
|
||||
SelectAll(value.Value, RenameItems);
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, List<ElementType>> GetCategoriesFromDocument()
|
||||
{
|
||||
var dict = new FilteredElementCollector(doc)
|
||||
.OfClass(typeof(ElementType))
|
||||
.Cast<ElementType>()
|
||||
.Where(t => t.CanBeRenamed && t.Category is { CategoryType: CategoryType.Model or CategoryType.Annotation, AllowsBoundParameters: true })
|
||||
.GroupBy(t => t.Category.Id)
|
||||
.ToDictionary(g => Category.GetCategory(doc, g.Key).Name, g => g.ToList());
|
||||
CategoryCount = dict.Count;
|
||||
return dict;
|
||||
//foreach (BuiltInCategory builtInCategory in Enum.GetValues(typeof(BuiltInCategory)))
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// var types = new FilteredElementCollector(doc).OfCategory(builtInCategory).WhereElementIsElementType().Cast<ElementType>().ToList();
|
||||
// if (types.Any() && types.Any(t => t.CanBeRenamed))
|
||||
// {
|
||||
// var category = types.FirstOrDefault()!.Category;
|
||||
// if (category is { CategoryType: CategoryType.Model or CategoryType.Annotation, AllowsBoundParameters: true })
|
||||
// {
|
||||
// var name = category.Name;
|
||||
// items.Add(builtInCategory, name);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// catch (Exception)
|
||||
// {
|
||||
// //string name = Enum.GetName(typeof(BuiltInCategory), builtInCategory);
|
||||
// //TaskDialog.Show( "错误", $"{name}");
|
||||
// }
|
||||
//}
|
||||
|
||||
//CategoryCount = items.Count;
|
||||
//return items.OrderBy(kv => kv.Value).ToDictionary(kv => kv.Key, kv => kv.Value);
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanModify))]
|
||||
private async Task ModifyName()
|
||||
{
|
||||
await Task.Delay(1_000);
|
||||
ModifyTypeName();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取列表中所有条目的新名称
|
||||
/// </summary>
|
||||
private void GetNewNames()
|
||||
{
|
||||
var selectedItems = RenameItems.Where(item => item.IsSelected);
|
||||
foreach (var renameItem in selectedItems)
|
||||
{
|
||||
var tempName = renameItem.OldTypeName;
|
||||
////手动修改的新名称不处理
|
||||
//if (!string.IsNullOrEmpty(renameItem.NewTypeName))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
if (!string.IsNullOrEmpty(FoundText))
|
||||
{
|
||||
tempName = tempName.Replace(FoundText, string.IsNullOrEmpty(ReplaceText) ? string.Empty : ReplaceText);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(PrefixText))
|
||||
{
|
||||
tempName = tempName.Insert(0, $"{PrefixText}{Separator}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(SuffixText))
|
||||
{
|
||||
tempName += $"{Separator}{SuffixText}";
|
||||
}
|
||||
|
||||
renameItem.NewTypeName = tempName;
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void GetRenameItems(IList items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
RenameItems = null!;
|
||||
CanInput = false;
|
||||
return;
|
||||
}
|
||||
|
||||
List<RenameTypeItem> symbolItems = [];
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is KeyValuePair<string, List<ElementType>> categoryItems)
|
||||
{
|
||||
foreach (var type in categoryItems.Value)
|
||||
{
|
||||
RenameTypeItem renameItem = new()
|
||||
{
|
||||
OldTypeName = type.Name,
|
||||
ElementType = type,
|
||||
CategoryName = categoryItems.Key,
|
||||
FamilyName = type.FamilyName
|
||||
};
|
||||
|
||||
symbolItems.Add(renameItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CanInput = symbolItems.Count > 0;
|
||||
RenameItems = symbolItems;
|
||||
|
||||
foreach (var renameItem in RenameItems)
|
||||
{
|
||||
renameItem.PropertyChanged += (_, args) =>
|
||||
{
|
||||
if (args.PropertyName == nameof(RenameTypeItem.IsSelected))
|
||||
{
|
||||
OnPropertyChanged(nameof(IsAllItemsSelected));
|
||||
//foreach (RenameTypeItem item in SelectedItems)
|
||||
//{
|
||||
// item.IsSelected = renameItem.IsSelected;
|
||||
//}
|
||||
ModifyNameCommand.NotifyCanExecuteChanged();
|
||||
if (string.IsNullOrEmpty(renameItem.NewTypeName))
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
}
|
||||
//if (args.PropertyName == nameof(RenameTypeItem.NewTypeName))
|
||||
//{
|
||||
// ModifyTypeName();
|
||||
//}
|
||||
};
|
||||
}
|
||||
|
||||
//IsAllItemsSelected = true;
|
||||
}
|
||||
|
||||
private void ModifyTypeName()
|
||||
{
|
||||
var needToRename = RenameItems.Where(item => item.IsSelected);
|
||||
using Transaction ts = new(doc, "修改类型名称");
|
||||
ts.Start();
|
||||
|
||||
foreach (var renameItem in needToRename)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(renameItem.NewTypeName))
|
||||
{
|
||||
renameItem.ElementType.Name = renameItem.NewTypeName;
|
||||
renameItem.OldTypeName = renameItem.NewTypeName;
|
||||
}
|
||||
}
|
||||
|
||||
ts.Commit();
|
||||
}
|
||||
|
||||
partial void OnFoundTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnPrefixTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnReplaceTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnSearchTextChanged(string value)
|
||||
{
|
||||
Collection = allCategories.Where(kv => string.IsNullOrEmpty(value) || kv.Key.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
.ToDictionary(k => k.Key, v => v.Value);
|
||||
CategoryCount = Collection.Count;
|
||||
//CategoriesCollectionView.Refresh();
|
||||
}
|
||||
|
||||
partial void OnSeparatorChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
partial void OnSuffixTextChanged(string value)
|
||||
{
|
||||
GetNewNames();
|
||||
}
|
||||
|
||||
private static void SelectAll(bool select, IEnumerable<RenameTypeItem> models)
|
||||
{
|
||||
foreach (var model in models)
|
||||
{
|
||||
model.IsSelected = select;
|
||||
}
|
||||
}
|
||||
}
|
||||
136
ShrlAlgo.RvKits/RvFamily/ReplaceInstanceCmd.cs
Normal file
136
ShrlAlgo.RvKits/RvFamily/ReplaceInstanceCmd.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.DB.Structure;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
/// <summary>
|
||||
/// 替换族实例
|
||||
/// </summary>
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class ReplaceInstanceCmd : ExternalCommand
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
var elementIds = new List<ElementId>();
|
||||
if (
|
||||
UiDocument.SelectObject(
|
||||
new FuncFilter(
|
||||
e =>
|
||||
e is FamilyInstance instance
|
||||
&& instance.Symbol.Family.FamilyPlacementType is FamilyPlacementType.OneLevelBased or FamilyPlacementType.WorkPlaneBased or FamilyPlacementType.TwoLevelsBased
|
||||
),
|
||||
"请选择目标族实例"
|
||||
)
|
||||
is not FamilyInstance instanceToMatch
|
||||
)
|
||||
{
|
||||
Result = Result.Cancelled;
|
||||
return;
|
||||
}
|
||||
|
||||
var instancesReplace = UiDocument.SelectObjects(
|
||||
new FuncFilter(e => e is FamilyInstance instance && instance.Id != instanceToMatch.Id),
|
||||
"请选择被替换(修改)的族实例"
|
||||
).Cast<FamilyInstance>();
|
||||
if (!instancesReplace.Any())
|
||||
{
|
||||
Result = Result.Cancelled;
|
||||
return;
|
||||
}
|
||||
Document.Invoke(
|
||||
_ =>
|
||||
{
|
||||
instanceToMatch.Symbol.Activate();
|
||||
foreach (var instanceReplace in instancesReplace)
|
||||
{
|
||||
//跳过相同的实例
|
||||
if (instanceReplace.Id == instanceToMatch.Id)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var p1 = instanceReplace.GetLocXYZ();
|
||||
var p2 = instanceReplace.HandOrientation;
|
||||
//默认当前平面视图标高
|
||||
var level = Document.ActiveView.GenLevel;
|
||||
var placementType = instanceToMatch.Symbol.Family.FamilyPlacementType;
|
||||
FamilyInstance newInstance = null;
|
||||
switch (placementType)
|
||||
{
|
||||
case FamilyPlacementType.OneLevelBased:
|
||||
|
||||
{
|
||||
newInstance = Document.Create.NewFamilyInstance(
|
||||
p1,
|
||||
instanceToMatch.Symbol,
|
||||
level,
|
||||
StructuralType.NonStructural
|
||||
);
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.TwoLevelsBased:
|
||||
|
||||
{
|
||||
level = Document.GetElement(instanceToMatch.LevelId) as Level;
|
||||
newInstance = Document.Create.NewFamilyInstance(
|
||||
p1,
|
||||
instanceToMatch.Symbol,
|
||||
level,
|
||||
StructuralType.NonStructural
|
||||
);
|
||||
}
|
||||
break;
|
||||
case FamilyPlacementType.WorkPlaneBased:
|
||||
|
||||
{
|
||||
newInstance = Document.Create.NewFamilyInstance(
|
||||
level.GetPlaneReference(),
|
||||
p1,
|
||||
p2,
|
||||
instanceToMatch.Symbol
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
foreach (Parameter paramSource in instanceReplace.Parameters)
|
||||
{
|
||||
//var defini = paramSource.Definition as InternalDefinition;
|
||||
var b =
|
||||
paramSource.Definition is InternalDefinition definition
|
||||
&& (
|
||||
definition.BuiltInParameter != BuiltInParameter.INVALID
|
||||
&& definition.BuiltInParameter != BuiltInParameter.DOOR_NUMBER
|
||||
&& definition.BuiltInParameter != BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS
|
||||
);
|
||||
if (b || paramSource.IsReadOnly || !paramSource.HasValue)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (Parameter paramToWrite in newInstance.Parameters)
|
||||
{
|
||||
if (paramSource.Definition.Name == paramToWrite.Definition.Name)
|
||||
{
|
||||
paramToWrite.SetValue(paramSource.GetValue());
|
||||
}
|
||||
}
|
||||
Document.Regenerate();
|
||||
}
|
||||
|
||||
elementIds.Add(instanceReplace.Id);
|
||||
}
|
||||
|
||||
Document.Delete(elementIds);
|
||||
},
|
||||
"替换族实例"
|
||||
);
|
||||
}
|
||||
}
|
||||
330
ShrlAlgo.RvKits/RvFamily/UpgradeFamilyCmd.cs
Normal file
330
ShrlAlgo.RvKits/RvFamily/UpgradeFamilyCmd.cs
Normal file
@@ -0,0 +1,330 @@
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Autodesk.Revit.Attributes;
|
||||
using Autodesk.Revit.DB;
|
||||
using Autodesk.Revit.UI;
|
||||
|
||||
using Microsoft.Win32;
|
||||
|
||||
using Nice3point.Revit.Toolkit.External;
|
||||
|
||||
using ShrlAlgo.RvKits.Windows;
|
||||
|
||||
using WPFluent.Controls;
|
||||
|
||||
using TaskDialog = Autodesk.Revit.UI.TaskDialog;
|
||||
|
||||
namespace ShrlAlgo.RvKits.RvFamily;
|
||||
|
||||
[Transaction(TransactionMode.Manual)]
|
||||
[Regeneration(RegenerationOption.Manual)]
|
||||
public class UpgradeFamilyCmd : ExternalCommand
|
||||
{
|
||||
|
||||
private List<string> fileNames;
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
try
|
||||
{
|
||||
fileNames = GetSelectedFileNames();
|
||||
if (fileNames.Count > 0)
|
||||
{
|
||||
var progressMonitorViewModel = new ProgressBarManager<string>(UiDocument, fileNames, UpdateFile, "更新文件");
|
||||
progressMonitorViewModel.ProgressModal();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e is not Autodesk.Revit.Exceptions.OperationCanceledException)
|
||||
{
|
||||
ErrorMessage = e.Message;
|
||||
Result = Result.Failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取选择全路径文件名列表
|
||||
/// </summary>
|
||||
private static List<string> GetSelectedFileNames()
|
||||
{
|
||||
var taskDialog = new TaskDialog("选择方式")
|
||||
{
|
||||
MainInstruction = "选择方式",
|
||||
MainContent = "请选择方式"
|
||||
//FooterText = "<a href=\"http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=2484975 \">"
|
||||
//+ "进入revit开发中心</a>"
|
||||
};
|
||||
taskDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink1, "选择文件");
|
||||
taskDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink2, "选择文件夹");
|
||||
var tResult = taskDialog.Show();
|
||||
var list = new List<string>();
|
||||
switch (tResult)
|
||||
{
|
||||
case TaskDialogResult.CommandLink1:
|
||||
{
|
||||
var filter = "族文件|*.rfa";
|
||||
var openFile = new OpenFileDialog
|
||||
{
|
||||
Multiselect = true,
|
||||
Filter = filter
|
||||
};
|
||||
openFile.ShowDialog();
|
||||
if (openFile.FileNames.Length != 0)
|
||||
{
|
||||
var strFiles = openFile.FileNames;
|
||||
|
||||
foreach (var file in strFiles)
|
||||
{
|
||||
list.Add(file);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TaskDialogResult.CommandLink2:
|
||||
{
|
||||
var dialog = new VistaFolderBrowserDialog
|
||||
{
|
||||
Multiselect = false
|
||||
};
|
||||
dialog.ShowDialog();
|
||||
|
||||
if (dialog.SelectedPath != null)
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(dialog.SelectedPath);
|
||||
var files = directoryInfo.GetFiles("*.rfa", SearchOption.AllDirectories);
|
||||
foreach (var file in files)
|
||||
{
|
||||
list.Add(file.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private void UpdateFile(UIDocument uidoc, string filename, object obj)
|
||||
{
|
||||
System.Threading.Thread.Sleep(50);
|
||||
|
||||
if (File.GetAttributes(filename).ToString().IndexOf("ReadOnly", StringComparison.Ordinal) != -1)
|
||||
{
|
||||
File.SetAttributes(filename, FileAttributes.Normal);
|
||||
}
|
||||
|
||||
Document famdoc;
|
||||
try
|
||||
{
|
||||
famdoc = Application.OpenDocumentFile(filename);
|
||||
}
|
||||
catch (Autodesk.Revit.Exceptions.CorruptModelException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (famdoc.IsFamilyDocument)
|
||||
{
|
||||
using var trans = new Transaction(famdoc);
|
||||
trans.Start("删除多余属性值");
|
||||
var fm = famdoc.FamilyManager;
|
||||
if (fm.CurrentType == null)
|
||||
{
|
||||
var t = Path.GetFileNameWithoutExtension(filename);
|
||||
fm.NewType(t);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var familyParameter = fm.get_Parameter(BuiltInParameter.ALL_MODEL_URL);
|
||||
if (familyParameter != null)
|
||||
{
|
||||
fm.Set(familyParameter, string.Empty);
|
||||
}
|
||||
|
||||
familyParameter = fm.get_Parameter(BuiltInParameter.ALL_MODEL_TYPE_COMMENTS);
|
||||
if (familyParameter != null)
|
||||
{
|
||||
fm.Set(familyParameter, string.Empty);
|
||||
}
|
||||
|
||||
familyParameter = fm.get_Parameter(BuiltInParameter.ALL_MODEL_DESCRIPTION);
|
||||
if (familyParameter != null)
|
||||
{
|
||||
fm.Set(familyParameter, string.Empty);
|
||||
}
|
||||
|
||||
familyParameter = fm.get_Parameter(BuiltInParameter.KEYNOTE_PARAM);
|
||||
if (familyParameter != null)
|
||||
{
|
||||
fm.Set(familyParameter, string.Empty);
|
||||
}
|
||||
|
||||
familyParameter = fm.get_Parameter(BuiltInParameter.UNIFORMAT_CODE);
|
||||
if (familyParameter != null)
|
||||
{
|
||||
fm.Set(familyParameter, string.Empty);
|
||||
}
|
||||
|
||||
familyParameter = fm.get_Parameter(BuiltInParameter.ALL_MODEL_MODEL);
|
||||
if (familyParameter != null)
|
||||
{
|
||||
fm.Set(familyParameter, string.Empty);
|
||||
}
|
||||
|
||||
var fampara = fm.get_Parameter("族库大师");
|
||||
if (fampara != null)
|
||||
{
|
||||
fm.RemoveParameter(fampara);
|
||||
}
|
||||
var hostobjects = new FilteredElementCollector(famdoc)
|
||||
.OfClass(typeof(HostObject)).ToElementIds();
|
||||
var rplanes = new FilteredElementCollector(famdoc)
|
||||
.OfCategory(BuiltInCategory.OST_CLines).ToElementIds();
|
||||
var dimids = new FilteredElementCollector(famdoc)
|
||||
.OfClass(typeof(Dimension)).ToElementIds();
|
||||
var conids = new FilteredElementCollector(famdoc)
|
||||
.OfClass(typeof(ConnectorElement)).ToElementIds();
|
||||
//ICollection<ElementId> curids = new FilteredElementCollector(famdoc).OfClass(typeof(CurveElement)).ToElementIds();
|
||||
var textnotes = new FilteredElementCollector(famdoc)
|
||||
.OfClass(typeof(TextNote)).ToElementIds();
|
||||
var lightsources = new FilteredElementCollector(famdoc)
|
||||
.OfCategory(BuiltInCategory.OST_LightingFixtureSource).ToElementIds();
|
||||
var lights = new FilteredElementCollector(famdoc)
|
||||
.OfCategory(BuiltInCategory.OST_LightingFixtures).ToElementIds();
|
||||
var sketchgrids = new FilteredElementCollector(famdoc)
|
||||
.OfCategory(BuiltInCategory.OST_IOSSketchGrid).ToElementIds();
|
||||
var modelcurves = new FilteredElementCollector(famdoc)
|
||||
.OfCategory(BuiltInCategory.OST_ReferenceLines).ToElementIds();
|
||||
var facebox =
|
||||
new FilteredElementCollector(famdoc).OfClass(typeof(Extrusion));
|
||||
//UiDocument.ActiveView = v3d;
|
||||
//UIView uIView = UiDocument.GetOpenUIViews().Where(x => x.ViewId == v3d.ViewId).FirstOrDefault();
|
||||
//uIView.ZoomToFit();
|
||||
var setting = famdoc.GetDocumentPreviewSettings();
|
||||
var previewid = famdoc.FindPreviewId<View3D>(setting);
|
||||
setting.PreviewViewId = previewid;
|
||||
var v = famdoc.GetElement(previewid) as View;
|
||||
setting.ForceViewUpdate(true);
|
||||
//得到基于面的族样板拉伸体
|
||||
if (facebox.Count() != 0)
|
||||
{
|
||||
var boxs = from x in facebox
|
||||
where Math.Abs(x.get_Parameter(BuiltInParameter.EXTRUSION_END_PARAM).AsDouble() - -1) < 0.0001
|
||||
select x.Id;
|
||||
var elementIds = boxs.ToList();
|
||||
if (elementIds.Count() != 0)
|
||||
{
|
||||
v.HideElementsTemporary(elementIds);
|
||||
}
|
||||
}
|
||||
//var graphicDisplayOptions = v3d.get_Parameter(BuiltInParameter.MODEL_GRAPHICS_STYLE);
|
||||
//graphicDisplayOptions.Set(8);
|
||||
|
||||
v.DisplayStyle = DisplayStyle.RealisticWithEdges;
|
||||
v.DetailLevel = ViewDetailLevel.Fine;
|
||||
ThinLinesOptions.AreThinLinesEnabled = true;
|
||||
v.HideElementsTemporary(hostobjects);
|
||||
v.HideElementsTemporary(rplanes);
|
||||
v.HideElementsTemporary(dimids);
|
||||
v.HideElementsTemporary(conids);
|
||||
v.HideElementsTemporary(textnotes);
|
||||
v.HideElementsTemporary(lights);
|
||||
v.HideElementsTemporary(lightsources);
|
||||
v.HideElementsTemporary(sketchgrids);
|
||||
v.HideElementsTemporary(modelcurves);
|
||||
#if REVIT2018 || REVIT2020
|
||||
var ele = famdoc.GetElement(new ElementId(1537));
|
||||
#elif REVIT2025
|
||||
var ele = famdoc.GetElement(ElementId.Parse("1537"));
|
||||
#endif
|
||||
if (ele != null)
|
||||
{
|
||||
v.HideElementTemporary(ele.Id);
|
||||
}
|
||||
|
||||
if (v is View3D)
|
||||
{
|
||||
var v3d = v as View3D;
|
||||
if (v3d.IsLocked)
|
||||
{
|
||||
v3d.Unlock();
|
||||
}
|
||||
|
||||
if (famdoc.OwnerFamily.FamilyCategory ==
|
||||
Category.GetCategory(famdoc, BuiltInCategory.OST_LightingFixtures))
|
||||
{
|
||||
v3d.OrientTo(new XYZ(-1, 1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
//人看向视图的视角向量
|
||||
//v3d.OrientTo(new XYZ(-1, 1, -1));
|
||||
v3d.OrientTo(new XYZ(-1, -1, -1));
|
||||
}
|
||||
|
||||
//v3d.OrientTo(new XYZ(1, -1, -1));
|
||||
}
|
||||
|
||||
//XYZ eyeposition = new XYZ();
|
||||
//XYZ updirection = XYZ.BasisZ;
|
||||
//XYZ forwarddirection = XYZ.BasisY;
|
||||
//ViewOrientation3D orientation3D = new ViewOrientation3D(eyeposition,updirection,forwarddirection);
|
||||
//v3d.SetOrientation(orientation3D);
|
||||
//UiDocument.RefreshActiveView();
|
||||
//v3d.ToggleToIsometric();
|
||||
//System.Windows.Forms.SendKeys.SendWait("TL");
|
||||
ThinLinesOptions.AreThinLinesEnabled = true;
|
||||
var sa = new SaveAsOptions
|
||||
{
|
||||
OverwriteExistingFile = true,
|
||||
PreviewViewId = previewid
|
||||
};
|
||||
//SetViewSaveOption(famdoc, v3d, sa, setting);
|
||||
|
||||
trans.Commit();
|
||||
famdoc.SaveAs(filename, sa);
|
||||
famdoc.Close(false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//if (ex.GetType() == typeof(OperationCanceledException))
|
||||
//{
|
||||
// if (trans.HasStarted())
|
||||
// {
|
||||
// trans.Commit();
|
||||
// famdoc.CloseTrigger(false);
|
||||
// }
|
||||
// break;
|
||||
//}
|
||||
if (trans.HasStarted())
|
||||
{
|
||||
trans.Commit();
|
||||
famdoc.Close(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else //不是族文件时
|
||||
{
|
||||
var sa = new SaveAsOptions
|
||||
{
|
||||
OverwriteExistingFile = true
|
||||
};
|
||||
famdoc.SaveAs(filename, sa);
|
||||
famdoc.Close(false);
|
||||
}
|
||||
var isMatch = Regex.IsMatch(filename, ".\\d{4}(.rfa)");
|
||||
if (isMatch)
|
||||
{
|
||||
File.Delete(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user