Hi all,
I have a problem with (re)loading a family symbol.
// FamilySymbol ophalen vanuit familyName en familytype name
fs = new FilteredElementCollector(doc)
.OfClass(typeof(FamilySymbol))
.Cast<FamilySymbol>()
.FirstOrDefault(x => x.FamilyName == familyName && x.Name == familyTypeName);
CustomFamilyLoadOptions load_options = new CustomFamilyLoadOptions();
// Als niet aanwezig is dan inladen
if (fs == null)
{
if (!doc.LoadFamilySymbol(familyPath, familyTypeName, load_options, out fs))
{
TaskDialog.Show("Error", "Er gaat iets mis met het inladen van de family.");
fs = null;
}
}
else if(fs != null)
{
// content versie xml ophalen
string contentVersieXml = selectedFileData.ContentVersie.Replace("Contentversie: ", "");
// Contentversie uit symbol halen
string contVersieFamily = fs.LookupParameter("NLRS_C_content_versie")?.AsString();
if(contentVersieXml != contVersieFamily)
{
bool result = doc.LoadFamilySymbol(familyPath, familyTypeName, load_options, out fs);
if (!result)
{
TaskDialog.Show("Error", "Er gaat iets mis met het (her)inladen van de family.");
fs = null;
}
}
}
When I use the debug function, the first familysymbol i try to reload is reloading well.
The parameters are change and everything is fine.
The second family type that I try reload fails, the result is true but the IFamilyLoadOptions doesn't activate.
Here is my IFamilyLoadOptions, the first time the debug is writing this line:
OnFamilyFound _ FamilyInUse: True - overwriteParameterValues True"
The second time there is no debug.
/// <summary>
/// Methode hoe de family ingeladen moet worden.
/// Als family gevonden wordt dan overschrijft de family de parameters.
/// Als Shared family gevonden worden de subcomponenten ook overschrijven.
/// </summary>
[Transaction(TransactionMode.Manual)]
public class CustomFamilyLoadOptions : IFamilyLoadOptions
{
public bool OnFamilyFound(bool familyInUse, out bool overwriteParameterValues)
{
// Als de familie al in gebruik is, beslissen we hier of we deze willen overschrijven of niet.
// In dit voorbeeld zullen we de familie altijd overschrijven, zelfs als deze in gebruik is.
overwriteParameterValues = true;
Debug.WriteLine($"OnFamilyFound _ FamilyInUse: {familyInUse} - overwriteParameterValues {overwriteParameterValues}");
return true;
}
public bool OnSharedFamilyFound(Family sharedFamily, bool familyInUse, out FamilySource source, out bool overwriteParameterValues)
{
// Als een gedeelde familie wordt gevonden, kunnen we hier beslissen of we deze willen laden of niet.
// In dit voorbeeld zullen we de gedeelde familie altijd laden, zelfs als deze al in gebruik is.
source = FamilySource.Family;
overwriteParameterValues = true;
Debug.WriteLine($"OnSharedFamilyFound _ sharedFamily: {sharedFamily} - familyInUse {familyInUse} - source {source} - overwriteParameterValues {overwriteParameterValues}");
return true;
}
}
I found this example in the SDK:
@jeremytammik is there a specific reason that this example is creating a temp file?
KG
Jan Willem
Solved! Go to Solution.
Solved by ricaun. Go to Solution.
I did not read all your code.
However, just looking at this line:
fs = new FilteredElementCollector(doc)
I would assume that the resulting variable fs will never be null, even if the resulting collection is empty. If so, that might explain why the following statement will never be true, and the code in the if-scope will never execute:
else if(fs != null)
I would suggest always running your dubious code in the debugger to step through it line by line and see what happens.
Thanks for the response @jeremy_tammik
The fs started as : FamilySymbol fs = null;
That's the weird thing, the result is true.
But the IFamilyLoadOptions is not activated. Is that because the modify date of the family isnt change?
The 'NLRS_C_content_versie' is a type parameter?
You are using the LoadFamilySymbol to load a symbol in a existent Family.
That's a good questing if the IFamilyLoadOptions should trigger with a FamilySymbol conflict.
Yes, the parameter is a type parameter.
I try to reload it in a project.
The IFamilyLoadOptions doesn't trigger.. i guess because the family is already in the project by the first action, but I reloaded a specific symbol.
I see a remark on the OnFamilyFound bool, it says should only trigger when family is changed, in this case it isnt ...
I tried to create a temp file, but nothing works
Hi @jw.vanasselt,
I haven't looked into the full code, maybe a variable is re-used or something...
But keep in mind filtering for a Symbol only using it's familyname and typename CAN return others if the Category isn't taken into account. Familynames across categories can be thesame.
Given that with the typename the chance is low. I never use FirstOrDefault in such case, but test the collector on count = 1 (Or use Single/SingleOrDefault) -> Well not for UserFamilies..So would be relative save as long as they aren't named after system families (A window family "Walls" can exist...)
Does the Type come from the family file or a TypeCatalog?
From the documentation:
Return Value
True if the family type/symbol was loaded successfully into the project, otherwise False. -> So not sure what happens if the type values are changed in the project but the Family file on disk isn't. -> In the UI this won't trigger a warning and no option to overwrite the values of the family type in the project.
If you change something to the Family File (new type + delete type) it's seen as changed, maybe same for the API version?
I would test it out with a small controlled code snipplet (fixed family name, maybe even fixed ID...) in the API and see what it does in each situation + identical test in the UI (Same unchanged family and a updated family from disk).
I'm doing some unit test to understand what is happening, and when loading the same family file the LoadFamily return false even if I change the parameters in the symbols. The LoadFamilySymbol return true but the parameter in the type is not replaced.
Looks like the main Family need to be changed in some way to make IFamilyLoadOptions to trigger and replace the parameters.
If you change the type parameter and try to load the family again, if is the same file does not seen to replace the parameters. I tried to copy the file, and didn't work. Only if I changed the Family and reload in some way in the project.
Here is the test project:
And what if it's loaded from another location?
The location a family is loaded from is available in the project, so that should update if loaded from another location....
I tried to copy the file to a different folder and Revit is smart to know that is the same file, is not gonna reload a family that is already loaded.
Is you rename you gonna need to find all the instances and replace with the new family, and could be some reference you could forget to swap.
Another way would be to open the family changed something without changing and reload in the document. The next time you try to load the same family should be different and IFamilyLoadOptions trigger and the type parameter is replaced.
This code force to open the family, change the current type name and rollback, and load back in the document.
FamilyUtils.EditLoadFamily(document, FamilyUtils.SelectFamily(document, FamilyName), (familyDocument) =>
{
using (Transaction transaction = new Transaction(familyDocument))
{
transaction.Start("Change Family");
var name = familyDocument.FamilyManager.CurrentType.Name;
familyDocument.FamilyManager.RenameCurrentType(name + $" {DateTime.UtcNow.Ticks}");
familyDocument.FamilyManager.RenameCurrentType(name);
transaction.Commit();
}
});
The only problem could be if you have a big document and this could take a while to regenerate the document after reload the family.
Here is the FamilyUtils class:
This example has been edited, if I see correctly the family from the project?
I have the changed family in a central environment, with this action he will open and reload the current one (in the project). But the symbol that is present in the project is outdated and cannot be orderded.
Or did I miss a line of code?
Got it!
Forgot to reload the Family Symbol first before edit that family ๐
Thanks alot!
Depending on Family (and number of) doesn't this add a huge amount of time to update a family, seems a bit overkill?
If the family from disk and in project is detected by Revit as identical, why not retrieve the type values of the Disk Family by opening it in the background, reading it's type values of the needed type and push those back into the project.
And better even, if a TypeCatalog is used (or a cached dataset of the values) the updating would be even quicker. (as you are already doing with the ContentVersion XML)
Btw; if the ContentVersion is different shouldn't the family be different, and LoadFamilySymbol work, or can this also refer to changes in parameter values? And in that case (if only a parameter value is changed) does LoadFamilySymbol then also not work/overwrite?
Just wondering what the use case is for this?
- Michel
Ps. I have several tools that push data into the model elements based on some criteria outside or in the model, but I only push data that's different and the user gets notification of x-items changed (and which), so to reduce access to elements in regards to worksharing/ownership and time. My advise is; only overwrite what's needed.
That's a good point, and I will definitely look into it. Do you have any examples you could share to demonstrate how you are handling this in your tools? It would be helpful to see how you manage pushing only the necessary data.
Kind Regards,
Jan Willem
Can't find what you're looking for? Ask the community or share your knowledge.